From 51f4870d4215dcf99a0aab1ad989cbe06871849b Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Mon, 6 Jan 2025 13:18:39 +0000 Subject: [PATCH 1/6] Update core repo files --- .vscode/analyzersettings.psd1 | 147 ++++-- .vscode/settings.json | 21 +- RequiredModules.psd1 | 38 +- Resolve-Dependency.ps1 | 961 ++++++++++++++++++++++++++++------ Resolve-Dependency.psd1 | 10 + azure-pipelines.yml | 2 +- build.ps1 | 40 +- build.yaml | 73 ++- 8 files changed, 1048 insertions(+), 244 deletions(-) diff --git a/.vscode/analyzersettings.psd1 b/.vscode/analyzersettings.psd1 index 78312d2..d925a62 100644 --- a/.vscode/analyzersettings.psd1 +++ b/.vscode/analyzersettings.psd1 @@ -1,44 +1,115 @@ @{ - CustomRulePath = '.\output\RequiredModules\DscResource.AnalyzerRules' - includeDefaultRules = $true - IncludeRules = @( - # DSC Resource Kit style guideline rules. - 'PSAvoidDefaultValueForMandatoryParameter', - 'PSAvoidDefaultValueSwitchParameter', - 'PSAvoidInvokingEmptyMembers', - 'PSAvoidNullOrEmptyHelpMessageAttribute', - 'PSAvoidUsingCmdletAliases', - 'PSAvoidUsingComputerNameHardcoded', - 'PSAvoidUsingDeprecatedManifestFields', - 'PSAvoidUsingEmptyCatchBlock', - 'PSAvoidUsingInvokeExpression', - 'PSAvoidUsingPositionalParameters', - 'PSAvoidShouldContinueWithoutForce', - 'PSAvoidUsingWMICmdlet', - 'PSAvoidUsingWriteHost', - 'PSDSCReturnCorrectTypesForDSCFunctions', - 'PSDSCStandardDSCFunctionsInResource', - 'PSDSCUseIdenticalMandatoryParametersForDSC', - 'PSDSCUseIdenticalParametersForDSC', - 'PSMisleadingBacktick', - 'PSMissingModuleManifestField', - 'PSPossibleIncorrectComparisonWithNull', - 'PSProvideCommentHelp', - 'PSReservedCmdletChar', - 'PSReservedParams', - 'PSUseApprovedVerbs', - 'PSUseCmdletCorrectly', - 'PSUseOutputTypeCorrectly', - 'PSAvoidGlobalVars', - 'PSAvoidUsingConvertToSecureStringWithPlainText', - 'PSAvoidUsingPlainTextForPassword', - 'PSAvoidUsingUsernameAndPasswordParams', - 'PSDSCUseVerboseMessageInDSCResource', - 'PSShouldProcess', - 'PSUseDeclaredVarsMoreThanAssignments', - 'PSUsePSCredentialType', + CustomRulePath = @( + './output/RequiredModules/DscResource.AnalyzerRules' + './output/RequiredModules/Indented.ScriptAnalyzerRules' + ) + IncludeDefaultRules = $true + IncludeRules = @( + # DSC Community style guideline rules from the module ScriptAnalyzer. + 'PSAvoidDefaultValueForMandatoryParameter' + 'PSAvoidDefaultValueSwitchParameter' + 'PSAvoidInvokingEmptyMembers' + 'PSAvoidNullOrEmptyHelpMessageAttribute' + 'PSAvoidUsingCmdletAliases' + 'PSAvoidUsingComputerNameHardcoded' + 'PSAvoidUsingDeprecatedManifestFields' + 'PSAvoidUsingEmptyCatchBlock' + 'PSAvoidUsingInvokeExpression' + 'PSAvoidUsingPositionalParameters' + 'PSAvoidShouldContinueWithoutForce' + 'PSAvoidUsingWMICmdlet' + 'PSAvoidUsingWriteHost' + 'PSDSCReturnCorrectTypesForDSCFunctions' + 'PSDSCStandardDSCFunctionsInResource' + 'PSDSCUseIdenticalMandatoryParametersForDSC' + 'PSDSCUseIdenticalParametersForDSC' + 'PSMisleadingBacktick' + 'PSMissingModuleManifestField' + 'PSPossibleIncorrectComparisonWithNull' + 'PSProvideCommentHelp' + 'PSReservedCmdletChar' + 'PSReservedParams' + 'PSUseApprovedVerbs' + 'PSUseCmdletCorrectly' + 'PSUseOutputTypeCorrectly' + 'PSAvoidGlobalVars' + 'PSAvoidUsingConvertToSecureStringWithPlainText' + 'PSAvoidUsingPlainTextForPassword' + 'PSAvoidUsingUsernameAndPasswordParams' + 'PSDSCUseVerboseMessageInDSCResource' + 'PSShouldProcess' + 'PSUseDeclaredVarsMoreThanAssignments' + 'PSUsePSCredentialType' + + # Additional rules from the module ScriptAnalyzer + 'PSUseConsistentWhitespace' + 'UseCorrectCasing' + 'PSPlaceOpenBrace' + 'PSPlaceCloseBrace' + 'AlignAssignmentStatement' + 'AvoidUsingDoubleQuotesForConstantString' + 'UseShouldProcessForStateChangingFunctions' + # Rules from the modules DscResource.AnalyzerRules 'Measure-*' + + # Rules from the module Indented.ScriptAnalyzerRules + 'AvoidCreatingObjectsFromAnEmptyString' + 'AvoidDashCharacters' + 'AvoidEmptyNamedBlocks' + 'AvoidFilter' + 'AvoidHelpMessage' + 'AvoidNestedFunctions' + 'AvoidNewObjectToCreatePSObject' + 'AvoidParameterAttributeDefaultValues' + 'AvoidProcessWithoutPipeline' + 'AvoidSmartQuotes' + 'AvoidThrowOutsideOfTry' + 'AvoidWriteErrorStop' + 'AvoidWriteOutput' + 'UseSyntacticallyCorrectExamples' ) + <# + The following types are not rules but parse errors reported by PSScriptAnalyzer + so they cannot be ecluded. They need to be filtered out from the result of + Invoke-ScriptAnalyzer. + + TypeNotFound - Because classes in the project cannot be found unless built. + RequiresModuleInvalid - Because 'using module' in prefix.ps1 cannot be resolved as source file. + #> + ExcludeRules = @() + + Rules = @{ + PSUseConsistentWhitespace = @{ + Enable = $true + CheckOpenBrace = $true + CheckInnerBrace = $true + CheckOpenParen = $true + CheckOperator = $false + CheckSeparator = $true + CheckPipe = $true + CheckPipeForRedundantWhitespace = $true + CheckParameter = $false + } + + PSPlaceOpenBrace = @{ + Enable = $true + OnSameLine = $false + NewLineAfter = $true + IgnoreOneLineBlock = $false + } + + PSPlaceCloseBrace = @{ + Enable = $true + NoEmptyLineBefore = $true + IgnoreOneLineBlock = $false + NewLineAfter = $true + } + + PSAlignAssignmentStatement = @{ + Enable = $true + CheckHashtable = $true + } + } } diff --git a/.vscode/settings.json b/.vscode/settings.json index 72f9013..0c162ce 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,8 +10,9 @@ "powershell.codeFormatting.pipelineIndentationStyle": "IncreaseIndentationForFirstPipeline", "powershell.codeFormatting.preset": "Custom", "powershell.codeFormatting.alignPropertyValuePairs": true, + "powershell.codeFormatting.useConstantStrings": true, "powershell.developer.bundledModulesPath": "${cwd}/output/RequiredModules", - "powershell.scriptAnalysis.settingsPath": ".vscode\\analyzersettings.psd1", + "powershell.scriptAnalysis.settingsPath": "/.vscode/analyzersettings.psd1", "powershell.scriptAnalysis.enable": true, "files.trimTrailingWhitespace": true, "files.trimFinalNewlines": true, @@ -19,6 +20,9 @@ "files.associations": { "*.ps1xml": "xml" }, + "cSpell.dictionaries": [ + "powershell" + ], "cSpell.words": [ "COMPANYNAME", "ICONURI", @@ -34,8 +38,21 @@ "pscmdlet", "steppable" ], + "cSpell.ignorePaths": [ + ".git" + ], "[markdown]": { "files.trimTrailingWhitespace": false, "files.encoding": "utf8" - } + }, + "powershell.pester.useLegacyCodeLens": false, + "pester.testFilePath": [ + "[tT]ests/[qQ][aA]/*.[tT]ests.[pP][sS]1", + "[tT]ests/[uU]nit/**/*.[tT]ests.[pP][sS]1", + "[tT]ests/[uU]nit/*.[tT]ests.[pP][sS]1" + ], + "pester.runTestsInNewProcess": true, + "pester.pesterModulePath": "./output/RequiredModules/Pester", + "powershell.pester.codeLens": true, + "pester.suppressCodeLensNotice": true, } diff --git a/RequiredModules.psd1 b/RequiredModules.psd1 index c875d80..9a10704 100644 --- a/RequiredModules.psd1 +++ b/RequiredModules.psd1 @@ -1,5 +1,5 @@ @{ - PSDependOptions = @{ + PSDependOptions = @{ AddToPath = $true Target = 'output\RequiredModules' Parameters = @{ @@ -7,18 +7,26 @@ } } - InvokeBuild = 'latest' - PSScriptAnalyzer = 'latest' - Pester = '4.10.1' - Plaster = 'latest' - ModuleBuilder = 'latest' - ChangelogManagement = 'latest' - Sampler = 'latest' - 'Sampler.GitHubTasks' = 'latest' - MarkdownLinkCheck = 'latest' - 'DscResource.Test' = 'latest' - 'DscResource.AnalyzerRules' = 'latest' - 'DscResource.DocGenerator' = 'latest' - 'DscResource.Common' = 'latest' - xDscResourceDesigner = 'latest' + InvokeBuild = 'latest' + PSScriptAnalyzer = 'latest' + Pester = '4.10.1' + Plaster = 'latest' + ModuleBuilder = 'latest' + ChangelogManagement = 'latest' + Sampler = 'latest' + 'Sampler.GitHubTasks' = 'latest' + MarkdownLinkCheck = 'latest' + 'DscResource.Test' = 'latest' + xDscResourceDesigner = 'latest' + + # Build dependencies needed for using the module + 'DscResource.Common' = 'latest' + + # Analyzer rules + 'DscResource.AnalyzerRules' = 'latest' + 'Indented.ScriptAnalyzerRules' = 'latest' + + # Prerequisite modules for documentation. + 'DscResource.DocGenerator' = 'latest' + PlatyPS = 'latest' } diff --git a/Resolve-Dependency.ps1 b/Resolve-Dependency.ps1 index e207b3e..17cc98e 100644 --- a/Resolve-Dependency.ps1 +++ b/Resolve-Dependency.ps1 @@ -9,7 +9,7 @@ .PARAMETER PSDependTarget Path for PSDepend to be bootstrapped and save other dependencies. Can also be CurrentUser or AllUsers if you wish to install the modules in - such scope. The default value is './output/RequiredModules' relative to + such scope. The default value is 'output/RequiredModules' relative to this script's path. .PARAMETER Proxy @@ -46,6 +46,21 @@ .PARAMETER WithYAML Not yet written. + .PARAMETER UseModuleFast + Specifies to use ModuleFast instead of PowerShellGet to resolve dependencies + faster. + + .PARAMETER ModuleFastBleedingEdge + Specifies to use ModuleFast code that is in the ModuleFast's main branch + in its GitHub repository. The parameter UseModuleFast must also be set to + true. + + .PARAMETER UsePSResourceGet + Specifies to use the new PSResourceGet module instead of the (now legacy) PowerShellGet module. + + .PARAMETER PSResourceGetVersion + String specifying the module version for PSResourceGet if the `UsePSResourceGet` switch is utilized. + .NOTES Load defaults for parameters values from Resolve-Dependency.psd1 if not provided as parameter. @@ -59,7 +74,7 @@ param [Parameter()] [System.String] - $PSDependTarget = (Join-Path -Path $PSScriptRoot -ChildPath './output/RequiredModules'), + $PSDependTarget = (Join-Path -Path $PSScriptRoot -ChildPath 'output/RequiredModules'), [Parameter()] [System.Uri] @@ -96,7 +111,39 @@ param [Parameter()] [System.Management.Automation.SwitchParameter] - $WithYAML + $WithYAML, + + [Parameter()] + [System.Collections.Hashtable] + $RegisterGallery, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $UseModuleFast, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ModuleFastBleedingEdge, + + [Parameter()] + [System.String] + $ModuleFastVersion, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $UsePSResourceGet, + + [Parameter()] + [System.String] + $PSResourceGetVersion, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $UsePowerShellGetCompatibilityModule, + + [Parameter()] + [System.String] + $UsePowerShellGetCompatibilityModuleVersion ) try @@ -107,17 +154,6 @@ try { Import-Module -Name Microsoft.PowerShell.Utility -RequiredVersion '3.1.0.0' } - - <# - Making sure the imported PackageManagement module is not from PS7 module - path. The VSCode PS extension is changing the $env:PSModulePath and - prioritize the PS7 path. This is an issue with PowerShellGet because - it loads an old version if available (or fail to load latest). - #> - Get-Module -ListAvailable PackageManagement | - Where-Object -Property 'ModuleBase' -NotMatch 'powershell.7' | - Select-Object -First 1 | - Import-Module -Force } Write-Verbose -Message 'Importing Bootstrap default parameters from ''$PSScriptRoot/Resolve-Dependency.psd1''.' @@ -138,7 +174,7 @@ try { if (-not $PSBoundParameters.Keys.Contains($parameterName) -and $resolveDependencyDefaults.ContainsKey($parameterName)) { - Write-Verbose -Message "Setting $parameterName with $($resolveDependencyDefaults[$parameterName])." + Write-Verbose -Message "Setting parameter '$parameterName' to value '$($resolveDependencyDefaults[$parameterName])'." try { @@ -151,7 +187,7 @@ try $PSBoundParameters.Add($parameterName, $variableValue) - Set-Variable -Name $parameterName -value $variableValue -Force -ErrorAction 'SilentlyContinue' + Set-Variable -Name $parameterName -Value $variableValue -Force -ErrorAction 'SilentlyContinue' } catch { @@ -165,253 +201,860 @@ catch Write-Warning -Message "Error attempting to import Bootstrap's default parameters from '$resolveDependencyConfigPath': $($_.Exception.Message)." } -Write-Progress -Activity 'Bootstrap:' -PercentComplete 0 -CurrentOperation 'NuGet Bootstrap' +# Handle when both ModuleFast and PSResourceGet is configured or/and passed as parameter. +if ($UseModuleFast -and $UsePSResourceGet) +{ + Write-Information -MessageData 'Both ModuleFast and PSResourceGet is configured or/and passed as parameter.' -InformationAction 'Continue' -# TODO: This should handle the parameter $AllowOldPowerShellGetModule. -$powerShellGetModule = Import-Module -Name 'PowerShellGet' -MinimumVersion '2.0' -ErrorAction 'SilentlyContinue' -PassThru + if ($PSVersionTable.PSVersion -ge '7.2') + { + $UsePSResourceGet = $false -# Install the package provider if it is not available. -$nuGetProvider = Get-PackageProvider -Name 'NuGet' -ListAvailable | Select-Object -First 1 + Write-Information -MessageData 'PowerShell 7.2 or higher being used, prefer ModuleFast over PSResourceGet.' -InformationAction 'Continue' + } + else + { + $UseModuleFast = $false -if (-not $powerShellGetModule -and -not $nuGetProvider) -{ - $providerBootstrapParameters = @{ - Name = 'nuget' - Force = $true - ForceBootstrap = $true - ErrorAction = 'Stop' + Write-Information -MessageData 'Windows PowerShell or PowerShell <=7.1 is being used, prefer PSResourceGet since ModuleFast is not supported on this version of PowerShell.' -InformationAction 'Continue' } +} - switch ($PSBoundParameters.Keys) +# Only bootstrap ModuleFast if it is not already imported. +if ($UseModuleFast -and -not (Get-Module -Name 'ModuleFast')) +{ + try { - 'Proxy' + $moduleFastBootstrapScriptBlockParameters = @{} + + if ($ModuleFastBleedingEdge) { - $providerBootstrapParameters.Add('Proxy', $Proxy) + Write-Information -MessageData 'ModuleFast is configured to use Bleeding Edge (directly from ModuleFast''s main branch).' -InformationAction 'Continue' + + $moduleFastBootstrapScriptBlockParameters.UseMain = $true } + elseif($ModuleFastVersion) + { + if ($ModuleFastVersion -notmatch 'v') + { + $ModuleFastVersion = 'v{0}' -f $ModuleFastVersion + } - 'ProxyCredential' + Write-Information -MessageData ('ModuleFast is configured to use version {0}.' -f $ModuleFastVersion) -InformationAction 'Continue' + + $moduleFastBootstrapScriptBlockParameters.Release = $ModuleFastVersion + } + else { - $providerBootstrapParameters.Add('ProxyCredential', $ProxyCredential) + Write-Information -MessageData 'ModuleFast is configured to use latest released version.' -InformationAction 'Continue' } - 'Scope' - { - $providerBootstrapParameters.Add('Scope', $Scope) + $moduleFastBootstrapUri = 'bit.ly/modulefast' # cSpell: disable-line + + Write-Debug -Message ('Using bootstrap script at {0}' -f $moduleFastBootstrapUri) + + $invokeWebRequestParameters = @{ + Uri = $moduleFastBootstrapUri + ErrorAction = 'Stop' } + + $moduleFastBootstrapScript = Invoke-WebRequest @invokeWebRequestParameters + + $moduleFastBootstrapScriptBlock = [ScriptBlock]::Create($moduleFastBootstrapScript) + + & $moduleFastBootstrapScriptBlock @moduleFastBootstrapScriptBlockParameters } + catch + { + Write-Warning -Message ('ModuleFast could not be bootstrapped. Reverting to PSResourceGet. Error: {0}' -f $_.Exception.Message) - if ($AllowPrerelease) + $UseModuleFast = $false + $UsePSResourceGet = $true + } +} + +if ($UsePSResourceGet) +{ + $psResourceGetModuleName = 'Microsoft.PowerShell.PSResourceGet' + + # If PSResourceGet was used prior it will be locked and we can't replace it. + if ((Test-Path -Path "$PSDependTarget/$psResourceGetModuleName" -PathType 'Container') -and (Get-Module -Name $psResourceGetModuleName)) { - $providerBootstrapParameters.Add('AllowPrerelease', $true) + Write-Information -MessageData ('{0} is already bootstrapped and imported into the session. If there is a need to refresh the module, open a new session and resolve dependencies again.' -f $psResourceGetModuleName) -InformationAction 'Continue' } + else + { + Write-Debug -Message ('{0} do not exist, saving the module to RequiredModules.' -f $psResourceGetModuleName) - Write-Information -MessageData 'Bootstrap: Installing NuGet Package Provider from the web (Make sure Microsoft addresses/ranges are allowed).' + $psResourceGetDownloaded = $false - $null = Install-PackageProvider @providerBootstrapParams + try + { + if (-not $PSResourceGetVersion) + { + # Default to latest version if no version is passed in parameter or specified in configuration. + $psResourceGetUri = "https://www.powershellgallery.com/api/v2/package/$psResourceGetModuleName" + } + else + { + $psResourceGetUri = "https://www.powershellgallery.com/api/v2/package/$psResourceGetModuleName/$PSResourceGetVersion" + } - $nuGetProvider = Get-PackageProvider -Name 'NuGet' -ListAvailable | Select-Object -First 1 + $invokeWebRequestParameters = @{ + # TODO: Should support proxy parameters passed to the script. + Uri = $psResourceGetUri + OutFile = "$PSDependTarget/$psResourceGetModuleName.nupkg" # cSpell: ignore nupkg + ErrorAction = 'Stop' + } - $nuGetProviderVersion = $nuGetProvider.Version.ToString() + $previousProgressPreference = $ProgressPreference + $ProgressPreference = 'SilentlyContinue' - Write-Information -MessageData "Bootstrap: Importing NuGet Package Provider version $nuGetProviderVersion to current session." + # Bootstrapping Microsoft.PowerShell.PSResourceGet. + Invoke-WebRequest @invokeWebRequestParameters - $Null = Import-PackageProvider -Name 'NuGet' -RequiredVersion $nuGetProviderVersion -Force -} + $ProgressPreference = $previousProgressPreference -Write-Progress -Activity 'Bootstrap:' -PercentComplete 10 -CurrentOperation "Ensuring Gallery $Gallery is trusted" + $psResourceGetDownloaded = $true + } + catch + { + Write-Warning -Message ('{0} could not be bootstrapped. Reverting to PowerShellGet. Error: {1}' -f $psResourceGetModuleName, $_.Exception.Message) + } -# Fail if the given PSGallery is not registered. -$previousGalleryInstallationPolicy = (Get-PSRepository -Name $Gallery -ErrorAction 'Stop').InstallationPolicy + $UsePSResourceGet = $false -Set-PSRepository -Name $Gallery -InstallationPolicy 'Trusted' -ErrorAction 'Ignore' + if ($psResourceGetDownloaded) + { + # On Windows PowerShell the command Expand-Archive do not like .nupkg as a zip archive extension. + $zipFileName = ((Split-Path -Path $invokeWebRequestParameters.OutFile -Leaf) -replace 'nupkg', 'zip') -try + $renameItemParameters = @{ + Path = $invokeWebRequestParameters.OutFile + NewName = $zipFileName + Force = $true + } + + Rename-Item @renameItemParameters + + $psResourceGetZipArchivePath = Join-Path -Path (Split-Path -Path $invokeWebRequestParameters.OutFile -Parent) -ChildPath $zipFileName + + $expandArchiveParameters = @{ + Path = $psResourceGetZipArchivePath + DestinationPath = "$PSDependTarget/$psResourceGetModuleName" + Force = $true + } + + Expand-Archive @expandArchiveParameters + + Remove-Item -Path $psResourceGetZipArchivePath + + Import-Module -Name $expandArchiveParameters.DestinationPath -Force + + # Successfully bootstrapped PSResourceGet, so let's use it. + $UsePSResourceGet = $true + } + } + + if ($UsePSResourceGet) + { + $psResourceGetModule = Get-Module -Name $psResourceGetModuleName + + $psResourceGetModuleVersion = $psResourceGetModule.Version.ToString() + + if ($psResourceGetModule.PrivateData.PSData.Prerelease) + { + $psResourceGetModuleVersion += '-{0}' -f $psResourceGetModule.PrivateData.PSData.Prerelease + } + + Write-Information -MessageData ('Using {0} v{1}.' -f $psResourceGetModuleName, $psResourceGetModuleVersion) -InformationAction 'Continue' + + if ($UsePowerShellGetCompatibilityModule) + { + $savePowerShellGetParameters = @{ + Name = 'PowerShellGet' + Path = $PSDependTarget + Repository = 'PSGallery' + TrustRepository = $true + } + + if ($UsePowerShellGetCompatibilityModuleVersion) + { + $savePowerShellGetParameters.Version = $UsePowerShellGetCompatibilityModuleVersion + + # Check if the version is a prerelease. + if ($UsePowerShellGetCompatibilityModuleVersion -match '\d+\.\d+\.\d+-.*') + { + $savePowerShellGetParameters.Prerelease = $true + } + } + + Save-PSResource @savePowerShellGetParameters + + Import-Module -Name "$PSDependTarget/PowerShellGet" + } + } +} + +# Check if legacy PowerShellGet and PSDepend must be bootstrapped. +if (-not ($UseModuleFast -or $UsePSResourceGet)) { - Write-Progress -Activity 'Bootstrap:' -PercentComplete 25 -CurrentOperation 'Checking PowerShellGet' + if ($PSVersionTable.PSVersion.Major -le 5) + { + <# + Making sure the imported PackageManagement module is not from PS7 module + path. The VSCode PS extension is changing the $env:PSModulePath and + prioritize the PS7 path. This is an issue with PowerShellGet because + it loads an old version if available (or fail to load latest). + #> + Get-Module -ListAvailable PackageManagement | + Where-Object -Property 'ModuleBase' -NotMatch 'powershell.7' | + Select-Object -First 1 | + Import-Module -Force + } + + Write-Progress -Activity 'Bootstrap:' -PercentComplete 0 -CurrentOperation 'NuGet Bootstrap' + + $importModuleParameters = @{ + Name = 'PowerShellGet' + MinimumVersion = '2.0' + MaximumVersion = '2.8.999' + ErrorAction = 'SilentlyContinue' + PassThru = $true + } - # Ensure the module is loaded and retrieve the version you have. - $powerShellGetVersion = (Import-Module -Name 'PowerShellGet' -PassThru -ErrorAction 'SilentlyContinue').Version + if ($AllowOldPowerShellGetModule) + { + $importModuleParameters.Remove('MinimumVersion') + } - Write-Verbose -Message "Bootstrap: The PowerShellGet version is $powerShellGetVersion" + $powerShellGetModule = Import-Module @importModuleParameters - # Versions below 2.0 are considered old, unreliable & not recommended - if (-not $powerShellGetVersion -or ($powerShellGetVersion -lt [System.Version] '2.0' -and -not $AllowOldPowerShellGetModule)) + # Install the package provider if it is not available. + $nuGetProvider = Get-PackageProvider -Name 'NuGet' -ListAvailable -ErrorAction 'SilentlyContinue' | + Select-Object -First 1 + + if (-not $powerShellGetModule -and -not $nuGetProvider) { - Write-Progress -Activity 'Bootstrap:' -PercentComplete 40 -CurrentOperation 'Installing newer version of PowerShellGet' - - $installPowerShellGetParameters = @{ - Name = 'PowerShellGet' - Force = $true - SkipPublisherCheck = $true - AllowClobber = $true - Scope = $Scope - Repository = $Gallery + $providerBootstrapParameters = @{ + Name = 'NuGet' + Force = $true + ForceBootstrap = $true + ErrorAction = 'Stop' + Scope = $Scope } switch ($PSBoundParameters.Keys) { 'Proxy' { - $installPowerShellGetParameters.Add('Proxy', $Proxy) + $providerBootstrapParameters.Add('Proxy', $Proxy) } 'ProxyCredential' { - $installPowerShellGetParameters.Add('ProxyCredential', $ProxyCredential) + $providerBootstrapParameters.Add('ProxyCredential', $ProxyCredential) } - 'GalleryCredential' + 'AllowPrerelease' { - $installPowerShellGetParameters.Add('Credential', $GalleryCredential) + $providerBootstrapParameters.Add('AllowPrerelease', $AllowPrerelease) } } - Write-Progress -Activity 'Bootstrap:' -PercentComplete 60 -CurrentOperation 'Installing newer version of PowerShellGet' - - Install-Module @installPowerShellGetParameters + Write-Information -MessageData 'Bootstrap: Installing NuGet Package Provider from the web (Make sure Microsoft addresses/ranges are allowed).' - Remove-Module -Name 'PowerShellGet' -Force -ErrorAction 'SilentlyContinue' - Remove-Module -Name 'PackageManagement' -Force + $null = Install-PackageProvider @providerBootstrapParameters - $powerShellGetModule = Import-Module PowerShellGet -Force -PassThru + $nuGetProvider = Get-PackageProvider -Name 'NuGet' -ListAvailable | Select-Object -First 1 - $powerShellGetVersion = $powerShellGetModule.Version.ToString() + $nuGetProviderVersion = $nuGetProvider.Version.ToString() - Write-Information -MessageData "Bootstrap: PowerShellGet version loaded is $powerShellGetVersion" - } + Write-Information -MessageData "Bootstrap: Importing NuGet Package Provider version $nuGetProviderVersion to current session." - # Try to import the PSDepend module from the available modules. - $getModuleParameters = @{ - Name = 'PSDepend' - ListAvailable = $true + $Null = Import-PackageProvider -Name 'NuGet' -RequiredVersion $nuGetProviderVersion -Force } - $psDependModule = Get-Module @getModuleParameters - - if ($PSBoundParameters.ContainsKey('MinimumPSDependVersion')) + if ($RegisterGallery) { - try + if ($RegisterGallery.ContainsKey('Name') -and -not [System.String]::IsNullOrEmpty($RegisterGallery.Name)) { - $psDependModule = $psDependModule | Where-Object -FilterScript { $_.Version -ge $MinimumPSDependVersion } + $Gallery = $RegisterGallery.Name } - catch + else { - throw ('There was a problem finding the minimum version of PSDepend. Error: {0}' -f $_) + $RegisterGallery.Name = $Gallery } + + Write-Progress -Activity 'Bootstrap:' -PercentComplete 7 -CurrentOperation "Verifying private package repository '$Gallery'" -Completed + + $previousRegisteredRepository = Get-PSRepository -Name $Gallery -ErrorAction 'SilentlyContinue' + + if ($previousRegisteredRepository.SourceLocation -ne $RegisterGallery.SourceLocation) + { + if ($previousRegisteredRepository) + { + Write-Progress -Activity 'Bootstrap:' -PercentComplete 9 -CurrentOperation "Re-registrering private package repository '$Gallery'" -Completed + + Unregister-PSRepository -Name $Gallery + + $unregisteredPreviousRepository = $true + } + else + { + Write-Progress -Activity 'Bootstrap:' -PercentComplete 9 -CurrentOperation "Registering private package repository '$Gallery'" -Completed + } + + Register-PSRepository @RegisterGallery + } + } + + Write-Progress -Activity 'Bootstrap:' -PercentComplete 10 -CurrentOperation "Ensuring Gallery $Gallery is trusted" + + # Fail if the given PSGallery is not registered. + $previousGalleryInstallationPolicy = (Get-PSRepository -Name $Gallery -ErrorAction 'Stop').Trusted + + $updatedGalleryInstallationPolicy = $false + + if ($previousGalleryInstallationPolicy -ne $true) + { + $updatedGalleryInstallationPolicy = $true + + # Only change policy if the repository is not trusted + Set-PSRepository -Name $Gallery -InstallationPolicy 'Trusted' -ErrorAction 'Ignore' } +} - if (-not $psDependModule) +try +{ + # Check if legacy PowerShellGet and PSDepend must be used. + if (-not ($UseModuleFast -or $UsePSResourceGet)) { - # PSDepend module not found, installing or saving it. - if ($PSDependTarget -in 'CurrentUser', 'AllUsers') + Write-Progress -Activity 'Bootstrap:' -PercentComplete 25 -CurrentOperation 'Checking PowerShellGet' + + # Ensure the module is loaded and retrieve the version you have. + $powerShellGetVersion = (Import-Module -Name 'PowerShellGet' -PassThru -ErrorAction 'SilentlyContinue').Version + + Write-Verbose -Message "Bootstrap: The PowerShellGet version is $powerShellGetVersion" + + # Versions below 2.0 are considered old, unreliable & not recommended + if (-not $powerShellGetVersion -or ($powerShellGetVersion -lt [System.Version] '2.0' -and -not $AllowOldPowerShellGetModule)) { - Write-Debug -Message "PSDepend module not found. Attempting to install from Gallery $Gallery." + Write-Progress -Activity 'Bootstrap:' -PercentComplete 40 -CurrentOperation 'Fetching newer version of PowerShellGet' + + # PowerShellGet module not found, installing or saving it. + if ($PSDependTarget -in 'CurrentUser', 'AllUsers') + { + Write-Debug -Message "PowerShellGet module not found. Attempting to install from Gallery $Gallery." + + Write-Warning -Message "Installing PowerShellGet in $PSDependTarget Scope." + + $installPowerShellGetParameters = @{ + Name = 'PowerShellGet' + Force = $true + SkipPublisherCheck = $true + AllowClobber = $true + Scope = $Scope + Repository = $Gallery + MaximumVersion = '2.8.999' + } + + switch ($PSBoundParameters.Keys) + { + 'Proxy' + { + $installPowerShellGetParameters.Add('Proxy', $Proxy) + } + + 'ProxyCredential' + { + $installPowerShellGetParameters.Add('ProxyCredential', $ProxyCredential) + } + + 'GalleryCredential' + { + $installPowerShellGetParameters.Add('Credential', $GalleryCredential) + } + } + + Write-Progress -Activity 'Bootstrap:' -PercentComplete 60 -CurrentOperation 'Installing newer version of PowerShellGet' + + Install-Module @installPowerShellGetParameters + } + else + { + Write-Debug -Message "PowerShellGet module not found. Attempting to Save from Gallery $Gallery to $PSDependTarget" + + $saveModuleParameters = @{ + Name = 'PowerShellGet' + Repository = $Gallery + Path = $PSDependTarget + Force = $true + MaximumVersion = '2.8.999' + } - Write-Warning -Message "Installing PSDepend in $PSDependTarget Scope." + Write-Progress -Activity 'Bootstrap:' -PercentComplete 60 -CurrentOperation "Saving PowerShellGet from $Gallery to $Scope" - $installPSDependParameters = @{ - Name = 'PSDepend' - Repository = $Gallery - Force = $true - Scope = $PSDependTarget - SkipPublisherCheck = $true - AllowClobber = $true + Save-Module @saveModuleParameters } - if ($MinimumPSDependVersion) + Write-Debug -Message 'Removing previous versions of PowerShellGet and PackageManagement from session' + + Get-Module -Name 'PowerShellGet' -All | Remove-Module -Force -ErrorAction 'SilentlyContinue' + Get-Module -Name 'PackageManagement' -All | Remove-Module -Force + + Write-Progress -Activity 'Bootstrap:' -PercentComplete 65 -CurrentOperation 'Loading latest version of PowerShellGet' + + Write-Debug -Message 'Importing latest PowerShellGet and PackageManagement versions into session' + + if ($AllowOldPowerShellGetModule) { - $installPSDependParameters.Add('MinimumVersion', $MinimumPSDependVersion) + $powerShellGetModule = Import-Module -Name 'PowerShellGet' -Force -PassThru } + else + { + Import-Module -Name 'PackageManagement' -MinimumVersion '1.4.8.1' -Force - Write-Progress -Activity 'Bootstrap:' -PercentComplete 75 -CurrentOperation "Installing PSDepend from $Gallery" + $powerShellGetModule = Import-Module -Name 'PowerShellGet' -MinimumVersion '2.2.5' -Force -PassThru + } - Install-Module @installPSDependParameters + $powerShellGetVersion = $powerShellGetModule.Version.ToString() + + Write-Information -MessageData "Bootstrap: PowerShellGet version loaded is $powerShellGetVersion" + } + + # Try to import the PSDepend module from the available modules. + $getModuleParameters = @{ + Name = 'PSDepend' + ListAvailable = $true } - else - { - Write-Debug -Message "PSDepend module not found. Attempting to Save from Gallery $Gallery to $PSDependTarget" - $saveModuleParameters = @{ - Name = 'PSDepend' - Repository = $Gallery - Path = $PSDependTarget - Force = $true + $psDependModule = Get-Module @getModuleParameters + + if ($PSBoundParameters.ContainsKey('MinimumPSDependVersion')) + { + try + { + $psDependModule = $psDependModule | Where-Object -FilterScript { $_.Version -ge $MinimumPSDependVersion } + } + catch + { + throw ('There was a problem finding the minimum version of PSDepend. Error: {0}' -f $_) } + } + + if (-not $psDependModule) + { + Write-Debug -Message 'PSDepend module not found.' - if ($MinimumPSDependVersion) + # PSDepend module not found, installing or saving it. + if ($PSDependTarget -in 'CurrentUser', 'AllUsers') { - $saveModuleParameters.add('MinimumVersion', $MinimumPSDependVersion) + Write-Debug -Message "Attempting to install from Gallery '$Gallery'." + + Write-Warning -Message "Installing PSDepend in $PSDependTarget Scope." + + $installPSDependParameters = @{ + Name = 'PSDepend' + Repository = $Gallery + Force = $true + Scope = $PSDependTarget + SkipPublisherCheck = $true + AllowClobber = $true + } + + if ($MinimumPSDependVersion) + { + $installPSDependParameters.Add('MinimumVersion', $MinimumPSDependVersion) + } + + Write-Progress -Activity 'Bootstrap:' -PercentComplete 75 -CurrentOperation "Installing PSDepend from $Gallery" + + Install-Module @installPSDependParameters + } + else + { + Write-Debug -Message "Attempting to Save from Gallery $Gallery to $PSDependTarget" + + $saveModuleParameters = @{ + Name = 'PSDepend' + Repository = $Gallery + Path = $PSDependTarget + Force = $true + } + + if ($MinimumPSDependVersion) + { + $saveModuleParameters.add('MinimumVersion', $MinimumPSDependVersion) + } + + Write-Progress -Activity 'Bootstrap:' -PercentComplete 75 -CurrentOperation "Saving PSDepend from $Gallery to $PSDependTarget" + + Save-Module @saveModuleParameters } + } - Write-Progress -Activity 'Bootstrap:' -PercentComplete 75 -CurrentOperation "Saving & Importing PSDepend from $Gallery to $Scope" + Write-Progress -Activity 'Bootstrap:' -PercentComplete 80 -CurrentOperation 'Importing PSDepend' - Save-Module @saveModuleParameters + $importModulePSDependParameters = @{ + Name = 'PSDepend' + ErrorAction = 'Stop' + Force = $true + } + + if ($PSBoundParameters.ContainsKey('MinimumPSDependVersion')) + { + $importModulePSDependParameters.Add('MinimumVersion', $MinimumPSDependVersion) } - } - Write-Progress -Activity 'Bootstrap:' -PercentComplete 80 -CurrentOperation 'Loading PSDepend' + # We should have successfully bootstrapped PSDepend. Fail if not available. + $null = Import-Module @importModulePSDependParameters - $importModulePSDependParameters = @{ - Name = 'PSDepend' - ErrorAction = 'Stop' - Force = $true + Write-Progress -Activity 'Bootstrap:' -PercentComplete 81 -CurrentOperation 'Invoke PSDepend' + + if ($WithYAML) + { + Write-Progress -Activity 'Bootstrap:' -PercentComplete 82 -CurrentOperation 'Verifying PowerShell module PowerShell-Yaml' + + if (-not (Get-Module -ListAvailable -Name 'PowerShell-Yaml')) + { + Write-Progress -Activity 'Bootstrap:' -PercentComplete 85 -CurrentOperation 'Installing PowerShell module PowerShell-Yaml' + + Write-Verbose -Message "PowerShell-Yaml module not found. Attempting to Save from Gallery '$Gallery' to '$PSDependTarget'." + + $SaveModuleParam = @{ + Name = 'PowerShell-Yaml' + Repository = $Gallery + Path = $PSDependTarget + Force = $true + } + + Save-Module @SaveModuleParam + } + else + { + Write-Verbose -Message 'PowerShell-Yaml is already available' + } + + Write-Progress -Activity 'Bootstrap:' -PercentComplete 88 -CurrentOperation 'Importing PowerShell module PowerShell-Yaml' + } } - if ($PSBoundParameters.ContainsKey('MinimumPSDependVersion')) + if (Test-Path -Path $DependencyFile) { - $importModulePSDependParameters.Add('MinimumVersion', $MinimumPSDependVersion) - } + if ($UseModuleFast -or $UsePSResourceGet) + { + $requiredModules = Import-PowerShellDataFile -Path $DependencyFile - # We should have successfully bootstrapped PSDepend. Fail if not available. - $null = Import-Module @importModulePSDependParameters + $requiredModules = $requiredModules.GetEnumerator() | + Where-Object -FilterScript { $_.Name -ne 'PSDependOptions' } - if ($WithYAML) - { - Write-Progress -Activity 'Bootstrap:' -PercentComplete 82 -CurrentOperation 'Verifying PowerShell module PowerShell-Yaml' + if ($UseModuleFast) + { + Write-Progress -Activity 'Bootstrap:' -PercentComplete 90 -CurrentOperation 'Invoking ModuleFast' - if (-not (Get-Module -ListAvailable -Name 'PowerShell-Yaml')) - { - Write-Progress -Activity 'Bootstrap:' -PercentComplete 85 -CurrentOperation 'Installing PowerShell module PowerShell-Yaml' + Write-Progress -Activity 'ModuleFast:' -PercentComplete 0 -CurrentOperation 'Restoring Build Dependencies' - Write-Verbose -Message "PowerShell-Yaml module not found. Attempting to Save from Gallery $Gallery to $PSDependTarget" + $modulesToSave = @( + 'PSDepend' # Always include PSDepend for backward compatibility. + ) - $SaveModuleParam = @{ - Name = 'PowerShell-Yaml' - Repository = $Gallery - Path = $PSDependTarget - Force = $true + if ($WithYAML) + { + $modulesToSave += 'PowerShell-Yaml' + } + + if ($UsePowerShellGetCompatibilityModule) + { + Write-Debug -Message 'PowerShellGet compatibility module is configured to be used.' + + # This is needed to ensure that the PowerShellGet compatibility module works. + $psResourceGetModuleName = 'Microsoft.PowerShell.PSResourceGet' + + if ($PSResourceGetVersion) + { + $modulesToSave += ('{0}:[{1}]' -f $psResourceGetModuleName, $PSResourceGetVersion) + } + else + { + $modulesToSave += $psResourceGetModuleName + } + + $powerShellGetCompatibilityModuleName = 'PowerShellGet' + + if ($UsePowerShellGetCompatibilityModuleVersion) + { + $modulesToSave += ('{0}:[{1}]' -f $powerShellGetCompatibilityModuleName, $UsePowerShellGetCompatibilityModuleVersion) + } + else + { + $modulesToSave += $powerShellGetCompatibilityModuleName + } + } + + foreach ($requiredModule in $requiredModules) + { + # If the RequiredModules.psd1 entry is an Hashtable then special handling is needed. + if ($requiredModule.Value -is [System.Collections.Hashtable]) + { + if (-not $requiredModule.Value.Version) + { + $requiredModuleVersion = 'latest' + } + else + { + $requiredModuleVersion = $requiredModule.Value.Version + } + + if ($requiredModuleVersion -eq 'latest') + { + $moduleNameSuffix = '' + + if ($requiredModule.Value.Parameters.AllowPrerelease -eq $true) + { + <# + Adding '!' to the module name indicate to ModuleFast + that is should also evaluate pre-releases. + #> + $moduleNameSuffix = '!' + } + + $modulesToSave += ('{0}{1}' -f $requiredModule.Name, $moduleNameSuffix) + } + else + { + $modulesToSave += ('{0}:[{1}]' -f $requiredModule.Name, $requiredModuleVersion) + } + } + else + { + if ($requiredModule.Value -eq 'latest') + { + $modulesToSave += $requiredModule.Name + } + else + { + # Handle different nuget version operators already present. + if ($requiredModule.Value -match '[!|:|[|(|,|>|<|=]') + { + $modulesToSave += ('{0}{1}' -f $requiredModule.Name, $requiredModule.Value) + } + else + { + # Assuming the version is a fixed version. + $modulesToSave += ('{0}:[{1}]' -f $requiredModule.Name, $requiredModule.Value) + } + } + } + } + + Write-Debug -Message ("Required modules to retrieve plan for:`n{0}" -f ($modulesToSave | Out-String)) + + $installModuleFastParameters = @{ + Destination = $PSDependTarget + DestinationOnly = $true + NoPSModulePathUpdate = $true + NoProfileUpdate = $true + Update = $true + Confirm = $false + } + + $moduleFastPlan = Install-ModuleFast -Specification $modulesToSave -Plan @installModuleFastParameters + + Write-Debug -Message ("Missing modules that need to be saved:`n{0}" -f ($moduleFastPlan | Out-String)) + + if ($moduleFastPlan) + { + # Clear all modules in plan from the current session so they can be fetched again. + $moduleFastPlan.Name | Get-Module | Remove-Module -Force + + $moduleFastPlan | Install-ModuleFast @installModuleFastParameters + } + else + { + Write-Verbose -Message 'All required modules were already up to date' + } + + Write-Progress -Activity 'ModuleFast:' -PercentComplete 100 -CurrentOperation 'Dependencies restored' -Completed } - Save-Module @SaveModuleParam + if ($UsePSResourceGet) + { + Write-Progress -Activity 'Bootstrap:' -PercentComplete 90 -CurrentOperation 'Invoking PSResourceGet' + + $modulesToSave = @( + @{ + Name = 'PSDepend' # Always include PSDepend for backward compatibility. + } + ) + + if ($WithYAML) + { + $modulesToSave += @{ + Name = 'PowerShell-Yaml' + } + } + + # Prepare hashtable that can be concatenated to the Save-PSResource parameters. + foreach ($requiredModule in $requiredModules) + { + # If the RequiredModules.psd1 entry is an Hashtable then special handling is needed. + if ($requiredModule.Value -is [System.Collections.Hashtable]) + { + $saveModuleHashtable = @{ + Name = $requiredModule.Name + } + + if ($requiredModule.Value.Version -and $requiredModule.Value.Version -ne 'latest') + { + $saveModuleHashtable.Version = $requiredModule.Value.Version + } + + if ($requiredModule.Value.Parameters.AllowPrerelease -eq $true) + { + $saveModuleHashtable.Prerelease = $true + } + + $modulesToSave += $saveModuleHashtable + } + else + { + if ($requiredModule.Value -eq 'latest') + { + $modulesToSave += @{ + Name = $requiredModule.Name + } + } + else + { + $modulesToSave += @{ + Name = $requiredModule.Name + Version = $requiredModule.Value + } + } + } + } + + $percentagePerModule = [System.Math]::Floor(100 / $modulesToSave.Length) + + $progressPercentage = 0 + + Write-Progress -Activity 'PSResourceGet:' -PercentComplete $progressPercentage -CurrentOperation 'Restoring Build Dependencies' + + foreach ($currentModule in $modulesToSave) + { + Write-Progress -Activity 'PSResourceGet:' -PercentComplete $progressPercentage -CurrentOperation 'Restoring Build Dependencies' -Status ('Saving module {0}' -f $savePSResourceParameters.Name) + + $savePSResourceParameters = @{ + Path = $PSDependTarget + TrustRepository = $true + Confirm = $false + } + + # Concatenate the module parameters to the Save-PSResource parameters. + $savePSResourceParameters += $currentModule + + # Modules that Sampler depend on that cannot be refreshed without a new session. + $skipModule = @('PowerShell-Yaml') + + if ($savePSResourceParameters.Name -in $skipModule -and (Get-Module -Name $savePSResourceParameters.Name)) + { + Write-Progress -Activity 'PSResourceGet:' -PercentComplete $progressPercentage -CurrentOperation 'Restoring Build Dependencies' -Status ('Skipping module {0}' -f $savePSResourceParameters.Name) + + Write-Information -MessageData ('Skipping the module {0} since it cannot be refresh while loaded into the session. To refresh the module open a new session and resolve dependencies again.' -f $savePSResourceParameters.Name) -InformationAction 'Continue' + } + else + { + # Clear all module from the current session so any new version fetched will be re-imported. + Get-Module -Name $savePSResourceParameters.Name | Remove-Module -Force + + Save-PSResource @savePSResourceParameters -ErrorVariable 'savePSResourceError' + + if ($savePSResourceError) + { + Write-Warning -Message 'Save-PSResource could not save (replace) one or more dependencies. This can be due to the module is loaded into the session (and referencing assemblies). Close the current session and open a new session and try again.' + } + } + + $progressPercentage += $percentagePerModule + } + + Write-Progress -Activity 'PSResourceGet:' -PercentComplete 100 -CurrentOperation 'Dependencies restored' -Completed + } } else { - Write-Verbose "PowerShell-Yaml is already available" + Write-Progress -Activity 'Bootstrap:' -PercentComplete 90 -CurrentOperation 'Invoking PSDepend' + + Write-Progress -Activity 'PSDepend:' -PercentComplete 0 -CurrentOperation 'Restoring Build Dependencies' + + $psDependParameters = @{ + Force = $true + Path = $DependencyFile + } + + # TODO: Handle when the Dependency file is in YAML, and -WithYAML is specified. + Invoke-PSDepend @psDependParameters + + Write-Progress -Activity 'PSDepend:' -PercentComplete 100 -CurrentOperation 'Dependencies restored' -Completed } } + else + { + Write-Warning -Message "The dependency file '$DependencyFile' could not be found." + } - Write-Progress -Activity 'Bootstrap:' -PercentComplete 90 -CurrentOperation 'Invoke PSDepend' - - Write-Progress -Activity "PSDepend:" -PercentComplete 0 -CurrentOperation "Restoring Build Dependencies" + Write-Progress -Activity 'Bootstrap:' -PercentComplete 100 -CurrentOperation 'Bootstrap complete' -Completed +} +finally +{ + if ($RegisterGallery) + { + Write-Verbose -Message "Removing private package repository '$Gallery'." + Unregister-PSRepository -Name $Gallery + } - if (Test-Path -Path $DependencyFile) + if ($unregisteredPreviousRepository) { - $psDependParameters = @{ - Force = $true - Path = $DependencyFile + Write-Verbose -Message "Reverting private package repository '$Gallery' to previous location URI:s." + + $registerPSRepositoryParameters = @{ + Name = $previousRegisteredRepository.Name + InstallationPolicy = $previousRegisteredRepository.InstallationPolicy } - # TODO: Handle when the Dependency file is in YAML, and -WithYAML is specified. - Invoke-PSDepend @psDependParameters + if ($previousRegisteredRepository.SourceLocation) + { + $registerPSRepositoryParameters.SourceLocation = $previousRegisteredRepository.SourceLocation + } + + if ($previousRegisteredRepository.PublishLocation) + { + $registerPSRepositoryParameters.PublishLocation = $previousRegisteredRepository.PublishLocation + } + + if ($previousRegisteredRepository.ScriptSourceLocation) + { + $registerPSRepositoryParameters.ScriptSourceLocation = $previousRegisteredRepository.ScriptSourceLocation + } + + if ($previousRegisteredRepository.ScriptPublishLocation) + { + $registerPSRepositoryParameters.ScriptPublishLocation = $previousRegisteredRepository.ScriptPublishLocation + } + + Register-PSRepository @registerPSRepositoryParameters } - Write-Progress -Activity "PSDepend:" -PercentComplete 100 -CurrentOperation "Dependencies restored" -Completed + if ($updatedGalleryInstallationPolicy -eq $true -and $previousGalleryInstallationPolicy -ne $true) + { + # Only try to revert installation policy if the repository exist + if ((Get-PSRepository -Name $Gallery -ErrorAction 'SilentlyContinue')) + { + # Reverting the Installation Policy for the given gallery if it was not already trusted + Set-PSRepository -Name $Gallery -InstallationPolicy 'Untrusted' + } + } - Write-Progress -Activity 'Bootstrap:' -PercentComplete 100 -CurrentOperation "Bootstrap complete" -Completed -} -finally -{ - # Reverting the Installation Policy for the given gallery - Set-PSRepository -Name $Gallery -InstallationPolicy $previousGalleryInstallationPolicy - Write-Verbose -Message "Project Bootstrapped, returning to Invoke-Build" + Write-Verbose -Message 'Project Bootstrapped, returning to Invoke-Build.' } diff --git a/Resolve-Dependency.psd1 b/Resolve-Dependency.psd1 index 2ae8c0d..07945f8 100644 --- a/Resolve-Dependency.psd1 +++ b/Resolve-Dependency.psd1 @@ -2,4 +2,14 @@ Gallery = 'PSGallery' AllowPrerelease = $false WithYAML = $true + + #UseModuleFast = $true + #ModuleFastVersion = '0.1.2' + #ModuleFastBleedingEdge = $true + + UsePSResourceGet = $true + #PSResourceGetVersion = '1.0.1' + + UsePowerShellGetCompatibilityModule = $true + UsePowerShellGetCompatibilityModuleVersion = '3.0.23-beta23' } diff --git a/azure-pipelines.yml b/azure-pipelines.yml index fef6bcc..6d46e39 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -28,7 +28,7 @@ stages: vmImage: 'windows-latest' steps: - pwsh: | - dotnet tool install --global GitVersion.Tool + dotnet tool install --global GitVersion.Tool --version 5.* $gitVersionObject = dotnet-gitversion | ConvertFrom-Json $gitVersionObject.PSObject.Properties.ForEach{ Write-Host -Object "Setting Task Variable '$($_.Name)' with value '$($_.Value)'." diff --git a/build.ps1 b/build.ps1 index b40a72e..f4a0fae 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,6 +1,6 @@ <# .DESCRIPTION - Bootstrap and build script for PowerShell module CI/CD pipeline + Bootstrap and build script for PowerShell module CI/CD pipeline. .PARAMETER Tasks The task or tasks to run. The default value is '.' (runs the default task). @@ -56,6 +56,19 @@ .PARAMETER AutoRestore Not yet written. + + .PARAMETER UseModuleFast + Specifies to use ModuleFast instead of PowerShellGet to resolve dependencies + faster. + + .PARAMETER UsePSResourceGet + Specifies to use PSResourceGet instead of PowerShellGet to resolve dependencies + faster. This can also be configured in Resolve-Dependency.psd1. + + .PARAMETER UsePowerShellGetCompatibilityModule + Specifies to use the compatibility module PowerShellGet. This parameter + only works then the method of downloading dependencies is PSResourceGet. + This can also be configured in Resolve-Dependency.psd1. #> [CmdletBinding()] param @@ -121,7 +134,19 @@ param [Parameter()] [System.Management.Automation.SwitchParameter] - $AutoRestore + $AutoRestore, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $UseModuleFast, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $UsePSResourceGet, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $UsePowerShellGetCompatibilityModule ) <# @@ -132,7 +157,6 @@ param process { - if ($MyInvocation.ScriptName -notLike '*Invoke-Build.ps1') { # Only run the process block through InvokeBuild (look at the Begin block at the bottom of this script). @@ -178,7 +202,7 @@ process ConvertFrom-Yaml -Yaml (Get-Content -Raw $configFile) } - # Native Support for JSON and JSONC (by Removing comments) + # Support for JSON and JSONC (by Removing comments) when module PowerShell-Yaml is available '\.[json|jsonc]' { $jsonFile = Get-Content -Raw -Path $configFile @@ -336,7 +360,7 @@ process } } -Begin +begin { # Find build config if not specified. if (-not $BuildConfig) @@ -356,7 +380,8 @@ Begin $BuildConfig = $config[0] } - else { + else + { $BuildConfig = $config } } @@ -449,7 +474,8 @@ Begin if ($ResolveDependency) { - Write-Host -Object "[pre-build] Resolving dependencies." -ForegroundColor Green + Write-Host -Object "[pre-build] Resolving dependencies using preferred method." -ForegroundColor Green + $resolveDependencyParams = @{ } # If BuildConfig is a Yaml file, bootstrap powershell-yaml via ResolveDependency. diff --git a/build.yaml b/build.yaml index c3e77f2..4b543fd 100644 --- a/build.yaml +++ b/build.yaml @@ -5,14 +5,34 @@ CopyPaths: - en-US - DSCResources - - Modules +Prefix: prefix.ps1 Encoding: UTF8 -VersionedOutputDirectory: true +BuiltModuleSubdirectory: builtModule + +ModuleBuildTasks: + Sampler: + - '*.build.Sampler.ib.tasks' + Sampler.GitHubTasks: + - '*.ib.tasks' + DscResource.DocGenerator: + - 'Task.*' + DscResource.Test: + - 'Task.*' + +TaskHeader: | + param($Path) + "" + "=" * 79 + Write-Build Cyan "`t`t`t$($Task.Name.replace("_"," ").ToUpper())" + Write-Build DarkGray "$(Get-BuildSynopsis $Task)" + "-" * 79 + Write-Build DarkGray " $Path" + Write-Build DarkGray " $($Task.InvocationInfo.ScriptName):$($Task.InvocationInfo.ScriptLineNumber)" + "" #################################################### # ModuleBuilder Submodules Configuration # #################################################### - NestedModule: DscResource.Common: CopyOnly: true @@ -33,11 +53,17 @@ BuildWorkflow: - Build_Module_ModuleBuilder - Build_NestedModules_ModuleBuilder - Create_Changelog_Release_Output + + docs: - Generate_Conceptual_Help - Generate_Wiki_Content + - Generate_Wiki_Sidebar + - Clean_Markdown_Metadata + - Package_Wiki_Content pack: - build + - docs - package_module_nupkg hqrmtest: @@ -45,6 +71,7 @@ BuildWorkflow: test: - Pester_Tests_Stop_On_Fail + - Convert_Pester_Coverage - Pester_If_Code_Coverage_Under_Threshold publish: @@ -67,6 +94,9 @@ Pester: CodeCoverageOutputFileEncoding: ascii CodeCoverageThreshold: 80 +#################################################### +# Pester Configuration (DscResource.Test) # +#################################################### DscTest: OutputFormat: NUnitXML ExcludeTag: @@ -77,25 +107,9 @@ DscTest: - Modules/DscResource.Common MainGitBranch: main -ModuleBuildTasks: - Sampler: - - '*.build.Sampler.ib.tasks' - Sampler.GitHubTasks: - - '*.ib.tasks' - DscResource.DocGenerator: - - 'Task.*' - -TaskHeader: | - param($Path) - "" - "=" * 79 - Write-Build Cyan "`t`t`t$($Task.Name.replace("_"," ").ToUpper())" - Write-Build DarkGray "$(Get-BuildSynopsis $Task)" - "-" * 79 - Write-Build DarkGray " $Path" - Write-Build DarkGray " $($Task.InvocationInfo.ScriptName):$($Task.InvocationInfo.ScriptLineNumber)" - "" - +#################################################### +# GitHub Configuration # +#################################################### GitHubConfig: GitHubFilesToAdd: - 'CHANGELOG.md' @@ -115,3 +129,18 @@ DscResource.DocGenerator: - '_(.+?)_' # Match Italic (underscore) - '\*\*(.+?)\*\*' # Match bold - '\*(.+?)\*' # Match Italic (asterisk) + Publish_GitHub_Wiki_Content: + Debug: false + Generate_Markdown_For_DSC_Resources: + MofResourceMetadata: + Type: MofResource + Category: Resources + ClassResourceMetadata: + Type: ClassResource + Category: Resources + CompositeResourceMetadata: + Type: CompositeResource + Category: Resources + Generate_Wiki_Sidebar: + Debug: false + AlwaysOverwrite: true From 77bec22db22f93b66ad132067e08f81b9ca8e16b Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Fri, 31 Jan 2025 16:21:29 +0000 Subject: [PATCH 2/6] Convert Common to buildable module --- build.yaml | 20 +- source/HyperVDsc.psd1 | 3 + source/HyperVDsc.psm1 | 1 + .../HyperVDsc.Common/HyperVDsc.Common.psd1 | 10 +- .../HyperVDsc.Common/HyperVDsc.Common.psm1 | 341 --- .../Private/Wait-VMIPAddress.ps1 | 40 + .../Public/ConvertFrom-TimeSpan.ps1 | 34 + .../Public/ConvertTo-TimeSpan.ps1 | 36 + .../HyperVDsc.Common/Public/Get-VMHyperV.ps1 | 28 + .../Public/Set-VMProperty.ps1 | 116 + .../HyperVDsc.Common/Public/Set-VMState.ps1 | 76 + source/Modules/HyperVDsc.Common/prefix.ps1 | 5 + tests/Unit/DSC_VHD.Tests.ps1 | 548 ++--- tests/Unit/DSC_VMDvdDrive.Tests.ps1 | 1388 ++++++------ tests/Unit/DSC_VMHardDiskDrive.Tests.ps1 | 462 ++-- tests/Unit/DSC_VMHost.Tests.ps1 | 722 +++--- tests/Unit/DSC_VMHyperV.Tests.ps1 | 1928 ++++++++--------- tests/Unit/DSC_VMNetworkAdapter.Tests.ps1 | 704 +++--- tests/Unit/DSC_VMProcessor.Tests.ps1 | 582 ++--- tests/Unit/DSC_VMScsiController.Tests.ps1 | 646 +++--- ...MSwitch_BandwidthReservationMode.Tests.ps1 | 958 ++++---- ...C_VMSwitch_EnableEmbeddedTeaming.Tests.ps1 | 988 ++++----- tests/Unit/DSC_VMSwitch_Id.Tests.ps1 | 752 +++---- tests/Unit/DSC_VhdFileDirectory.Tests.ps1 | 1062 ++++----- tests/Unit/HyperVDsc.Common.Tests.ps1 | 315 --- .../Private/Wait-VMIPAddress.Tests.ps1 | 64 + .../Public/ConvertFrom-TimeSpan.ps1 | 51 + .../Public/ConvertTo-TimeSpan.ps1 | 51 + .../HyperVDsc.Common/Public/Get-VMHyperV.ps1 | 68 + .../Public/Set-VMProperty.ps1 | 77 + .../HyperVDsc.Common/Public/Set-VMState.ps1 | 125 ++ 31 files changed, 6160 insertions(+), 6041 deletions(-) create mode 100644 source/HyperVDsc.psm1 delete mode 100644 source/Modules/HyperVDsc.Common/HyperVDsc.Common.psm1 create mode 100644 source/Modules/HyperVDsc.Common/Private/Wait-VMIPAddress.ps1 create mode 100644 source/Modules/HyperVDsc.Common/Public/ConvertFrom-TimeSpan.ps1 create mode 100644 source/Modules/HyperVDsc.Common/Public/ConvertTo-TimeSpan.ps1 create mode 100644 source/Modules/HyperVDsc.Common/Public/Get-VMHyperV.ps1 create mode 100644 source/Modules/HyperVDsc.Common/Public/Set-VMProperty.ps1 create mode 100644 source/Modules/HyperVDsc.Common/Public/Set-VMState.ps1 create mode 100644 source/Modules/HyperVDsc.Common/prefix.ps1 delete mode 100644 tests/Unit/HyperVDsc.Common.Tests.ps1 create mode 100644 tests/Unit/HyperVDsc.Common/Private/Wait-VMIPAddress.Tests.ps1 create mode 100644 tests/Unit/HyperVDsc.Common/Public/ConvertFrom-TimeSpan.ps1 create mode 100644 tests/Unit/HyperVDsc.Common/Public/ConvertTo-TimeSpan.ps1 create mode 100644 tests/Unit/HyperVDsc.Common/Public/Get-VMHyperV.ps1 create mode 100644 tests/Unit/HyperVDsc.Common/Public/Set-VMProperty.ps1 create mode 100644 tests/Unit/HyperVDsc.Common/Public/Set-VMState.ps1 diff --git a/build.yaml b/build.yaml index 4b543fd..f3e0655 100644 --- a/build.yaml +++ b/build.yaml @@ -5,7 +5,6 @@ CopyPaths: - en-US - DSCResources -Prefix: prefix.ps1 Encoding: UTF8 BuiltModuleSubdirectory: builtModule @@ -34,11 +33,20 @@ TaskHeader: | # ModuleBuilder Submodules Configuration # #################################################### NestedModule: - DscResource.Common: - CopyOnly: true - Path: ./output/RequiredModules/DscResource.Common - AddToManifest: false - Exclude: PSGetModuleInfo.xml + DscResource.Common: + CopyOnly: true + Path: ./output/RequiredModules/DscResource.Common + AddToManifest: false + Exclude: PSGetModuleInfo.xml + HyperVDsc.Common: + Prefix: prefix.ps1 + VersionedOutputDirectory: false + CopyPaths: + - en-US + Encoding: UTF8 + + AddToManifest: false + Exclude: PSGetModuleInfo.xml #################################################### # Pipeline Configuration # diff --git a/source/HyperVDsc.psd1 b/source/HyperVDsc.psd1 index f172ad5..39837f6 100644 --- a/source/HyperVDsc.psd1 +++ b/source/HyperVDsc.psd1 @@ -1,4 +1,7 @@ @{ + # Script module or binary module file associated with this manifest. + RootModule = 'HyperVDsc.psm1' + # Version number of this module. moduleVersion = '0.0.1' diff --git a/source/HyperVDsc.psm1 b/source/HyperVDsc.psm1 new file mode 100644 index 0000000..932b798 --- /dev/null +++ b/source/HyperVDsc.psm1 @@ -0,0 +1 @@ +# Empty file diff --git a/source/Modules/HyperVDsc.Common/HyperVDsc.Common.psd1 b/source/Modules/HyperVDsc.Common/HyperVDsc.Common.psd1 index 1ad8b7f..c4b09e8 100644 --- a/source/Modules/HyperVDsc.Common/HyperVDsc.Common.psd1 +++ b/source/Modules/HyperVDsc.Common/HyperVDsc.Common.psd1 @@ -30,14 +30,7 @@ Description = 'Functions used by the DSC resources in HyperVDsc.' # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. - FunctionsToExport = @( - 'Set-VMProperty' - 'Set-VMState' - 'Wait-VMIPAddress' - 'ConvertTo-TimeSpan' - 'ConvertFrom-TimeSpan' - 'Get-VMHyperV' - ) + FunctionsToExport = @() # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. CmdletsToExport = @() @@ -54,4 +47,3 @@ } # End of PSData hashtable } # End of PrivateData hashtable } - diff --git a/source/Modules/HyperVDsc.Common/HyperVDsc.Common.psm1 b/source/Modules/HyperVDsc.Common/HyperVDsc.Common.psm1 deleted file mode 100644 index 6795cf4..0000000 --- a/source/Modules/HyperVDsc.Common/HyperVDsc.Common.psm1 +++ /dev/null @@ -1,341 +0,0 @@ -$script:dscResourceCommonModulePath = Join-Path -Path $PSScriptRoot -ChildPath '../DscResource.Common' - -Import-Module -Name $script:dscResourceCommonModulePath - -$script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US' - -<# - .SYNOPSIS - Sets one or more virtual machine properties, powering the VM - off if required. - - .PARAMETER Name - Name of the virtual machine to apply the changes to. - - .PARAMETER VMName - Name of the virtual machine to apply the changes to. - - .PARAMETER VMCommand - The Hyper-V cmdlet name to call to enact the changes. - - .PARAMETER ChangeProperty - The collection of cmdlet parameter names and values to pass to the command. - - .PARAMETER WaitForIP - Waits for the virtual machine to report an IP address when transitioning - into a running state. - - .PARAMETER RestartIfNeeded - Power cycle the virtual machine if changes are required. -#> -function Set-VMProperty -{ - [CmdletBinding(DefaultParameterSetName = 'Name')] - param - ( - [Parameter(Mandatory = $true, ParameterSetName = 'Name')] - [System.String] - $Name, - - [Parameter(Mandatory = $true, ParameterSetName = 'VMName')] - [System.String] - $VMName, - - [Parameter(Mandatory = $true)] - [System.String] - $VMCommand, - - [Parameter(Mandatory = $true)] - [System.Collections.Hashtable] - $ChangeProperty, - - [Parameter()] - [System.Boolean] - $WaitForIP, - - [Parameter()] - [System.Boolean] - $RestartIfNeeded - ) - - if ($PSBoundParameters.ContainsKey('VMName')) - { - # Add the -Name property to the ChangeProperty hashtable for splatting - $ChangeProperty['VMName'] = $VMName - - # Set the common parameters for splatting against Get-VM and Set-VMState - $vmCommonProperty = @{ - Name = $VMName - } - - # Ensure that the name parameter is set for verbose messages - $Name = $VMName - } - else - { - # Add the -Name property to the ChangeProperty hashtable for splatting - $ChangeProperty['Name'] = $Name - - # Set the common parameters for splatting against Get-VM and Set-VMState - $vmCommonProperty = @{ - Name = $Name - } - } - - $vmObject = Get-VM @vmCommonProperty - $vmOriginalState = $vmObject.State - - if ($vmOriginalState -ne 'Off' -and $RestartIfNeeded) - { - # Turn the vm off to make changes - Set-VMState @vmCommonProperty -State Off - - Write-Verbose -Message ($script:localizedData.UpdatingVMProperties -f $Name) - # Make changes using the passed hashtable - & $VMCommand @ChangeProperty - - # Cannot move an off VM to a paused state - only to running state - if ($vmOriginalState -eq 'Running') - { - Set-VMState @vmCommonProperty -State Running -WaitForIP $WaitForIP - } - - Write-Verbose -Message ($script:localizedData.VMPropertiesUpdated -f $Name) - - # Cannot restore a vm to a paused state - if ($vmOriginalState -eq 'Paused') - { - Write-Warning -Message ($script:localizedData.VMStateWillBeOffWarning -f $Name) - } - } - elseif ($vmOriginalState -eq 'Off') - { - Write-Verbose -Message ($script:localizedData.UpdatingVMProperties -f $Name) - & $VMCommand @ChangeProperty - Write-Verbose -Message ($script:localizedData.VMPropertiesUpdated -f $Name) - } - else - { - $errorMessage = $script:localizedData.CannotUpdatePropertiesOnlineError -f $Name, $vmOriginalState - New-InvalidOperationException -Message $errorMessage - } -} #end function - -<# - .SYNOPSIS - Sets one or more virtual machine properties, powering the VM - off if required. - - .PARAMETER Name - Name of the virtual machine to apply the changes to. - - .PARAMETER State - The target power state of the virtual machine. - - .PARAMETER ChangeProperty - The collection of cmdlet parameter names and values to pass to the command. - - .PARAMETER WaitForIP - Waits for the virtual machine to be report an IP address when transitioning - into a running state. -#> -function Set-VMState -{ - [CmdletBinding()] - param - ( - [Parameter(Mandatory = $true)] - [Alias('VMName')] - [System.String] - $Name, - - [Parameter(Mandatory = $true)] - [ValidateSet('Running','Paused','Off')] - [System.String] - $State, - - [Parameter()] - [System.Boolean] - $WaitForIP - ) - - switch ($State) - { - 'Running' { - $vmCurrentState = (Get-VM -Name $Name).State - if ($vmCurrentState -eq 'Paused') - { - # If VM is in paused state, use resume-vm to make it running - Write-Verbose -Message ($script:localizedData.ResumingVM -f $Name) - Resume-VM -Name $Name - } - elseif ($vmCurrentState -eq 'Off') - { - # If VM is Off, use start-vm to make it running - Write-Verbose -Message ($script:localizedData.StartingVM -f $Name) - Start-VM -Name $Name - } - - if ($WaitForIP) - { - Wait-VMIPAddress -Name $Name -Verbose - } - } - 'Paused' { - if ($vmCurrentState -ne 'Off') - { - Write-Verbose -Message ($script:localizedData.SuspendingVM -f $Name) - Suspend-VM -Name $Name - } - } - 'Off' { - if ($vmCurrentState -ne 'Off') - { - Write-Verbose -Message ($script:localizedData.StoppingVM -f $Name) - Stop-VM -Name $Name -Force -WarningAction SilentlyContinue - } - } - } -} #end function - -<# - .SYNOPSIS - Waits for a virtual machine to be assigned an IP address. - - .PARAMETER Name - Name of the virtual machine to apply the changes to. - - .PARAMETER Timeout - Number of seconds to wait before timing out. Defaults to 300 (5 minutes). -#> -function Wait-VMIPAddress -{ - [CmdletBinding()] - param - ( - [Parameter(Mandatory = $true)] - [Alias('VMName')] - [System.String] - $Name, - - [Parameter()] - [System.Int32] - $Timeout = 300 - ) - - [System.Int32] $elapsedSeconds = 0 - while ((Get-VMNetworkAdapter -VMName $Name).IpAddresses.Count -lt 2) - { - Write-Verbose -Message ($script:localizedData.WaitingForVMIPAddress -f $Name) - Start-Sleep -Seconds 3 - - $elapsedSeconds += 3 - if ($elapsedSeconds -gt $Timeout) - { - $errorMessage = $script:localizedData.WaitForVMIPAddressTimeoutError -f $Name, $Timeout - - New-ObjectNotFoundException -Message $errorMessage - } - } -} #end function - -<# - .SYNOPSIS - Converts a number of seconds, minutes, hours or days into a System.TimeSpan object. - - .PARAMETER TimeInterval - The total number of seconds, minutes, hours or days to convert. - - .PARAMETER TimeSpanType - Convert using specified interval type. -#> -function ConvertTo-TimeSpan -{ - [CmdletBinding()] - [OutputType([System.TimeSpan])] - param - ( - [Parameter(Mandatory = $true)] - [System.UInt32] - $TimeInterval, - - [Parameter(Mandatory = $true)] - [ValidateSet('Seconds','Minutes','Hours','Days')] - [System.String] - $TimeIntervalType - ) - - $newTimeSpanParams = @{ } - switch ($TimeIntervalType) - { - 'Seconds' { $newTimeSpanParams['Seconds'] = $TimeInterval } - 'Minutes' { $newTimeSpanParams['Minutes'] = $TimeInterval } - 'Hours' { $newTimeSpanParams['Hours'] = $TimeInterval } - 'Days' { $newTimeSpanParams['Days'] = $TimeInterval } - } - return (New-TimeSpan @newTimeSpanParams) -} #end function ConvertTo-TimeSpan - -<# - .SYNOPSIS - Converts a System.TimeSpan into the number of seconds, minutes, hours or days. - - .PARAMETER TimeSpan - TimeSpan to convert into an integer - - .PARAMETER TimeSpanType - Convert timespan into the total number of seconds, minutes, hours or days. -#> -function ConvertFrom-TimeSpan -{ - [CmdletBinding()] - [OutputType([System.Int32])] - param - ( - [Parameter(Mandatory = $true)] - [System.TimeSpan] - $TimeSpan, - - [Parameter(Mandatory = $true)] - [ValidateSet('Seconds','Minutes','Hours','Days')] - [System.String] - $TimeSpanType - ) - - switch ($TimeSpanType) - { - 'Seconds' { return $TimeSpan.TotalSeconds -as [System.UInt32] } - 'Minutes' { return $TimeSpan.TotalMinutes -as [System.UInt32] } - 'Hours' { return $TimeSpan.TotalHours -as [System.UInt32] } - 'Days' { return $TimeSpan.TotalDays -as [System.UInt32] } - } -} #end function ConvertFrom-TimeSpan - -<# - .SYNOPSIS - Helper function for retrieving a virtual machine, ensuring only one VM is resolved - - .PARAMETER VMName - Name of the Hyper-V virtual machine to return -#> -function Get-VMHyperV -{ - [CmdletBinding()] - param - ( - [Parameter(Mandatory = $true)] - [System.String] - $VMName - ) - - $vm = Get-VM -Name $VMName -ErrorAction SilentlyContinue - - # Check if 1 or 0 VM with name = $name exist - if ($vm.count -gt 1) - { - $errorMessage = $script:localizedData.MoreThanOneVMExistsError -f $VMName - New-InvalidResultException -Message $errorMessage - } - - return $vm -} #end function Get-VMHyperV diff --git a/source/Modules/HyperVDsc.Common/Private/Wait-VMIPAddress.ps1 b/source/Modules/HyperVDsc.Common/Private/Wait-VMIPAddress.ps1 new file mode 100644 index 0000000..c077b89 --- /dev/null +++ b/source/Modules/HyperVDsc.Common/Private/Wait-VMIPAddress.ps1 @@ -0,0 +1,40 @@ +<# + .SYNOPSIS + Waits for a virtual machine to be assigned an IP address. + + .PARAMETER Name + Name of the virtual machine to apply the changes to. + + .PARAMETER Timeout + Number of seconds to wait before timing out. Defaults to 300 (5 minutes). +#> +function Wait-VMIPAddress +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [Alias('VMName')] + [System.String] + $Name, + + [Parameter()] + [System.Int32] + $Timeout = 300 + ) + + [System.Int32] $elapsedSeconds = 0 + while ((Get-VMNetworkAdapter -VMName $Name).IpAddresses.Count -lt 2) + { + Write-Verbose -Message ($script:localizedData.WaitingForVMIPAddress -f $Name) + Start-Sleep -Seconds 3 + + $elapsedSeconds += 3 + if ($elapsedSeconds -gt $Timeout) + { + $errorMessage = $script:localizedData.WaitForVMIPAddressTimeoutError -f $Name, $Timeout + + New-ObjectNotFoundException -Message $errorMessage + } + } +} #end function diff --git a/source/Modules/HyperVDsc.Common/Public/ConvertFrom-TimeSpan.ps1 b/source/Modules/HyperVDsc.Common/Public/ConvertFrom-TimeSpan.ps1 new file mode 100644 index 0000000..9c095b0 --- /dev/null +++ b/source/Modules/HyperVDsc.Common/Public/ConvertFrom-TimeSpan.ps1 @@ -0,0 +1,34 @@ +<# + .SYNOPSIS + Converts a System.TimeSpan into the number of seconds, minutes, hours or days. + + .PARAMETER TimeSpan + TimeSpan to convert into an integer + + .PARAMETER TimeSpanType + Convert timespan into the total number of seconds, minutes, hours or days. +#> +function ConvertFrom-TimeSpan +{ + [CmdletBinding()] + [OutputType([System.Int32])] + param + ( + [Parameter(Mandatory = $true)] + [System.TimeSpan] + $TimeSpan, + + [Parameter(Mandatory = $true)] + [ValidateSet('Seconds','Minutes','Hours','Days')] + [System.String] + $TimeSpanType + ) + + switch ($TimeSpanType) + { + 'Seconds' { return $TimeSpan.TotalSeconds -as [System.UInt32] } + 'Minutes' { return $TimeSpan.TotalMinutes -as [System.UInt32] } + 'Hours' { return $TimeSpan.TotalHours -as [System.UInt32] } + 'Days' { return $TimeSpan.TotalDays -as [System.UInt32] } + } +} #end function ConvertFrom-TimeSpan diff --git a/source/Modules/HyperVDsc.Common/Public/ConvertTo-TimeSpan.ps1 b/source/Modules/HyperVDsc.Common/Public/ConvertTo-TimeSpan.ps1 new file mode 100644 index 0000000..6da0a3d --- /dev/null +++ b/source/Modules/HyperVDsc.Common/Public/ConvertTo-TimeSpan.ps1 @@ -0,0 +1,36 @@ +<# + .SYNOPSIS + Converts a number of seconds, minutes, hours or days into a System.TimeSpan object. + + .PARAMETER TimeInterval + The total number of seconds, minutes, hours or days to convert. + + .PARAMETER TimeSpanType + Convert using specified interval type. +#> +function ConvertTo-TimeSpan +{ + [CmdletBinding()] + [OutputType([System.TimeSpan])] + param + ( + [Parameter(Mandatory = $true)] + [System.UInt32] + $TimeInterval, + + [Parameter(Mandatory = $true)] + [ValidateSet('Seconds','Minutes','Hours','Days')] + [System.String] + $TimeIntervalType + ) + + $newTimeSpanParams = @{ } + switch ($TimeIntervalType) + { + 'Seconds' { $newTimeSpanParams['Seconds'] = $TimeInterval } + 'Minutes' { $newTimeSpanParams['Minutes'] = $TimeInterval } + 'Hours' { $newTimeSpanParams['Hours'] = $TimeInterval } + 'Days' { $newTimeSpanParams['Days'] = $TimeInterval } + } + return (New-TimeSpan @newTimeSpanParams) +} #end function ConvertTo-TimeSpan diff --git a/source/Modules/HyperVDsc.Common/Public/Get-VMHyperV.ps1 b/source/Modules/HyperVDsc.Common/Public/Get-VMHyperV.ps1 new file mode 100644 index 0000000..011beb2 --- /dev/null +++ b/source/Modules/HyperVDsc.Common/Public/Get-VMHyperV.ps1 @@ -0,0 +1,28 @@ +<# + .SYNOPSIS + Helper function for retrieving a virtual machine, ensuring only one VM is resolved + + .PARAMETER VMName + Name of the Hyper-V virtual machine to return +#> +function Get-VMHyperV +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $VMName + ) + + $vm = Get-VM -Name $VMName -ErrorAction SilentlyContinue + + # Check if 1 or 0 VM with name = $name exist + if ($vm.count -gt 1) + { + $errorMessage = $script:localizedData.MoreThanOneVMExistsError -f $VMName + New-InvalidResultException -Message $errorMessage + } + + return $vm +} #end function Get-VMHyperV diff --git a/source/Modules/HyperVDsc.Common/Public/Set-VMProperty.ps1 b/source/Modules/HyperVDsc.Common/Public/Set-VMProperty.ps1 new file mode 100644 index 0000000..75d1ff8 --- /dev/null +++ b/source/Modules/HyperVDsc.Common/Public/Set-VMProperty.ps1 @@ -0,0 +1,116 @@ +<# + .SYNOPSIS + Sets one or more virtual machine properties, powering the VM + off if required. + + .PARAMETER Name + Name of the virtual machine to apply the changes to. + + .PARAMETER VMName + Name of the virtual machine to apply the changes to. + + .PARAMETER VMCommand + The Hyper-V cmdlet name to call to enact the changes. + + .PARAMETER ChangeProperty + The collection of cmdlet parameter names and values to pass to the command. + + .PARAMETER WaitForIP + Waits for the virtual machine to report an IP address when transitioning + into a running state. + + .PARAMETER RestartIfNeeded + Power cycle the virtual machine if changes are required. +#> +function Set-VMProperty +{ + [CmdletBinding(DefaultParameterSetName = 'Name')] + param + ( + [Parameter(Mandatory = $true, ParameterSetName = 'Name')] + [System.String] + $Name, + + [Parameter(Mandatory = $true, ParameterSetName = 'VMName')] + [System.String] + $VMName, + + [Parameter(Mandatory = $true)] + [System.String] + $VMCommand, + + [Parameter(Mandatory = $true)] + [System.Collections.Hashtable] + $ChangeProperty, + + [Parameter()] + [System.Boolean] + $WaitForIP, + + [Parameter()] + [System.Boolean] + $RestartIfNeeded + ) + + if ($PSBoundParameters.ContainsKey('VMName')) + { + # Add the -Name property to the ChangeProperty hashtable for splatting + $ChangeProperty['VMName'] = $VMName + + # Set the common parameters for splatting against Get-VM and Set-VMState + $vmCommonProperty = @{ + Name = $VMName + } + + # Ensure that the name parameter is set for verbose messages + $Name = $VMName + } + else + { + # Add the -Name property to the ChangeProperty hashtable for splatting + $ChangeProperty['Name'] = $Name + + # Set the common parameters for splatting against Get-VM and Set-VMState + $vmCommonProperty = @{ + Name = $Name + } + } + + $vmObject = Get-VM @vmCommonProperty + $vmOriginalState = $vmObject.State + + if ($vmOriginalState -ne 'Off' -and $RestartIfNeeded) + { + # Turn the vm off to make changes + Set-VMState @vmCommonProperty -State Off + + Write-Verbose -Message ($script:localizedData.UpdatingVMProperties -f $Name) + # Make changes using the passed hashtable + & $VMCommand @ChangeProperty + + # Cannot move an off VM to a paused state - only to running state + if ($vmOriginalState -eq 'Running') + { + Set-VMState @vmCommonProperty -State Running -WaitForIP $WaitForIP + } + + Write-Verbose -Message ($script:localizedData.VMPropertiesUpdated -f $Name) + + # Cannot restore a vm to a paused state + if ($vmOriginalState -eq 'Paused') + { + Write-Warning -Message ($script:localizedData.VMStateWillBeOffWarning -f $Name) + } + } + elseif ($vmOriginalState -eq 'Off') + { + Write-Verbose -Message ($script:localizedData.UpdatingVMProperties -f $Name) + & $VMCommand @ChangeProperty + Write-Verbose -Message ($script:localizedData.VMPropertiesUpdated -f $Name) + } + else + { + $errorMessage = $script:localizedData.CannotUpdatePropertiesOnlineError -f $Name, $vmOriginalState + New-InvalidOperationException -Message $errorMessage + } +} #end function diff --git a/source/Modules/HyperVDsc.Common/Public/Set-VMState.ps1 b/source/Modules/HyperVDsc.Common/Public/Set-VMState.ps1 new file mode 100644 index 0000000..d1d62eb --- /dev/null +++ b/source/Modules/HyperVDsc.Common/Public/Set-VMState.ps1 @@ -0,0 +1,76 @@ +<# + .SYNOPSIS + Sets one or more virtual machine properties, powering the VM + off if required. + + .PARAMETER Name + Name of the virtual machine to apply the changes to. + + .PARAMETER State + The target power state of the virtual machine. + + .PARAMETER ChangeProperty + The collection of cmdlet parameter names and values to pass to the command. + + .PARAMETER WaitForIP + Waits for the virtual machine to be report an IP address when transitioning + into a running state. +#> +function Set-VMState +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [Alias('VMName')] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [ValidateSet('Running','Paused','Off')] + [System.String] + $State, + + [Parameter()] + [System.Boolean] + $WaitForIP + ) + + switch ($State) + { + 'Running' { + $vmCurrentState = (Get-VM -Name $Name).State + if ($vmCurrentState -eq 'Paused') + { + # If VM is in paused state, use resume-vm to make it running + Write-Verbose -Message ($script:localizedData.ResumingVM -f $Name) + Resume-VM -Name $Name + } + elseif ($vmCurrentState -eq 'Off') + { + # If VM is Off, use start-vm to make it running + Write-Verbose -Message ($script:localizedData.StartingVM -f $Name) + Start-VM -Name $Name + } + + if ($WaitForIP) + { + Wait-VMIPAddress -Name $Name -Verbose + } + } + 'Paused' { + if ($vmCurrentState -ne 'Off') + { + Write-Verbose -Message ($script:localizedData.SuspendingVM -f $Name) + Suspend-VM -Name $Name + } + } + 'Off' { + if ($vmCurrentState -ne 'Off') + { + Write-Verbose -Message ($script:localizedData.StoppingVM -f $Name) + Stop-VM -Name $Name -Force -WarningAction SilentlyContinue + } + } + } +} #end function diff --git a/source/Modules/HyperVDsc.Common/prefix.ps1 b/source/Modules/HyperVDsc.Common/prefix.ps1 new file mode 100644 index 0000000..0d47385 --- /dev/null +++ b/source/Modules/HyperVDsc.Common/prefix.ps1 @@ -0,0 +1,5 @@ +$script:dscResourceCommonModulePath = Join-Path -Path $PSScriptRoot -ChildPath '../DscResource.Common' + +Import-Module -Name $script:dscResourceCommonModulePath + +$script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US' diff --git a/tests/Unit/DSC_VHD.Tests.ps1 b/tests/Unit/DSC_VHD.Tests.ps1 index 3b28e57..45d8cf1 100644 --- a/tests/Unit/DSC_VHD.Tests.ps1 +++ b/tests/Unit/DSC_VHD.Tests.ps1 @@ -1,274 +1,274 @@ -$script:dscModuleName = 'HyperVDsc' -$script:dscResourceName = 'DSC_Vhd' - -function Invoke-TestSetup -{ - try - { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' - } - catch [System.IO.FileNotFoundException] - { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' - } - - $script:testEnvironment = Initialize-TestEnvironment ` - -DSCModuleName $script:dscModuleName ` - -DSCResourceName $script:dscResourceName ` - -ResourceType 'Mof' ` - -TestType 'Unit' - - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -} - -function Invoke-TestCleanup -{ - Restore-TestEnvironment -TestEnvironment $script:testEnvironment -} - -Invoke-TestSetup - -try -{ - InModuleScope $script:dscResourceName { - Describe 'DSC_Vhd\Get-TargetResource' { - Context 'Should stop when Hyper-V module is missing' { - Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } -MockWith { - return $false - } - - It 'Should throw when the module is missing' { - { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | - Should -Throw 'Please ensure that Hyper-V role is installed with its PowerShell module' - } - } - - # 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 -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } - - Context 'VHD Present' { - It 'Should return a hashtable with Ensure being Present' { - Mock -CommandName Get-VHD -MockWith { - [pscustomobject]@{ - Path = 'server.vhdx' - } - } - - $getTargetResult = Get-TargetResource -Name 'server' -Path 'c:\boguspath' -Generation 'vhdx' - $getTargetResult.Ensure | Should -Be 'Present' - $getTargetResult | Should -BeOfType hashtable - } - } - - Context 'VHD Not Present' { - It 'Should return a hashtable with Ensure being Absent' { - Mock -CommandName Get-VHD - - $getTargetResult = Get-TargetResource -Name 'server' -Path 'c:\boguspath' -Generation 'vhdx' - $getTargetResult.Ensure | Should -Be 'Absent' - $getTargetResult | Should -BeOfType hashtable - } - } - } - - Describe 'DSC_Vhd\GetNameWithExtension' { - Context 'Name does not have extension' { - It 'Should return server.vhdx with generation vhdx' { - GetNameWithExtension -Name 'server' -Generation 'vhdx' | - Should -Be 'server.vhdx' - } - - It 'Should return server.vhd with generation vhd' { - GetNameWithExtension -Name 'server' -Generation 'vhd' | - Should -Be 'server.vhd' - } - - It 'Should not throw' { - { GetNameWithExtension -Name 'server' -Generation 'vhd' } | - Should -Not -throw - } - } - - Context 'Name has extension' { - It 'Should return server.vhdx with Name server.vhdx and generation vhdx' { - GetNameWithExtension -Name 'server.vhd' -Generation 'vhd' | - Should -Be 'server.vhd' - } - - It 'Should throw with mismatch with extension from name and generation' { - { GetNameWithExtension -Name 'server.vhdx' -Generation 'vhd' } | - Should -Throw 'the extension vhdx on the name does not match the generation vhd' - } - } - } - - Describe 'DSC_Vhd\Test-TargetResource' { - # Create an empty function to be able to mock the missing Hyper-V cmdlet - function Test-VHD - { - - } - - Context 'Should stop when Hyper-V module is missing' { - Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } -MockWith { - return $false - } - - It 'Should throw when the module is missing' { - { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | - Should -Throw 'Please ensure that Hyper-V role is installed with its PowerShell module' - } - } - - # 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 - } - - Context 'Parameter validation' { - It 'Fixed and Dynamic VHDs need MaximumSizeBytes specified' { - { Test-TargetResource -Name 'server' -Path 'C:\VMs' -Type 'Dynamic' } | - Should -Throw 'Specify MaximumSizeBytes property for Fixed and Dynamic VHDs.' - } - - It 'Parent Path is passed for a non Differencing disk' { - { Test-TargetResource -Name 'server' -Path 'C:\VMs' -ParentPath 'C:\VMs\Parent' -Type 'Fixed' -MaximumSizeBytes 1GB } | - Should -Throw 'Parent path is only supported for Differencing disks' - } - - It 'Differencing disk needs a Parent Path' { - { Test-TargetResource -Name 'server' -Path 'C:\VMs' -Type 'Differencing' } | - Should -Throw 'Differencing requires a parent path' - } - } - - Context 'ParentPath specified' { - It 'Should throw when ParentPath does not exist' { - Mock -CommandName Test-Path -MockWith { $false } - - { Test-TargetResource -Name 'server' -Path 'C:\VMs' -Type 'Differencing' -ParentPath 'c:\boguspath' } | - Should -Throw 'c:\boguspath does not exists' - } - - # "Generation $Generation should match ParentPath extension $($ParentPath.Split('.')[-1])" - It 'Should throw when file extension and generation have a mismatch' { - Mock -CommandName Test-Path -MockWith { $true } - - { Test-TargetResource -Name 'server' -Path 'C:\VMs' -Type 'Differencing' -ParentPath 'c:\boguspath.vhd' -Generation 'Vhdx' } | - Should -Throw 'Generation Vhdx should match ParentPath extension vhd' - } - } - - Context 'Path does not exist' { - It 'Should throw when the path does not exist' { - Mock -CommandName Test-Path -MockWith { $false } - - { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | - Should -Throw 'C:\VMs does not exists' - } - } - - Context 'Vhd exists' { - BeforeEach { - Mock -CommandName Test-Path -MockWith { $true } - Mock -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } - Mock -CommandName Test-VHD -MockWith { $true } - } - - It 'Should not throw' { - { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | - Should -not -throw - } - - It 'Should return a boolean and it should be true' { - $testResult = Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB - $testResult | Should -BeOfType bool - $testResult -eq $true | Should -Be $true - } - } - - Context 'Vhd does not exist' { - BeforeEach { - Mock -CommandName Test-Path -MockWith { $true } - Mock -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } - Mock -CommandName Test-VHD -MockWith { $false } - } - - It 'Should not throw' { - { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | - Should -not -throw - } - - It 'Should return a boolean and it should be false' { - $testResult = Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB - $testResult | Should -BeOfType bool - $testResult -eq $true | Should -Be $false - } - } - } - - Describe 'DSC_Vhd\Set-TargetResource' { - Context 'Ensure is Absent' { - Mock -CommandName Test-Path -MockWith { $true } - Mock -CommandName Remove-Item - Mock -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } - - It 'Should remove when Ensure is Absent and vhdx exists' { - $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -Ensure 'Absent' - Assert-MockCalled -CommandName Remove-Item -Times 1 -Exactly - } - } - - Context 'Ensure is Present' { - BeforeEach { - Mock -CommandName Get-VHD -MockWith { - [pscustomobject]@{ - Path = 'server.vhdx' - ParentPath = 'c:\boguspath\server.vhdx' - Size = 1073741824 - Type = 'Differencing' - } - } - - Mock -CommandName Set-VHD - Mock -CommandName Resize-VHD - Mock -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } - Mock -CommandName New-VHD - } - - It 'Should Create a VHD when Ensure is present and no VHD exists yet for non Differencing disk' { - Mock -CommandName Get-VHD -MockWith { throw } - - $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -Ensure 'Present' - Assert-MockCalled -CommandName New-VHD -Exactly -Times 1 -Scope It - } - - It 'Should Create a VHD when Ensure is present and no VHD exists yet for Differencing disk' { - Mock -CommandName Get-VHD -MockWith { throw } - - $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -Ensure 'Present' -ParentPath 'c:\boguspath\server.vhdx' -Type 'Differencing' - Assert-MockCalled -CommandName New-VHD -Exactly -Times 1 -Scope It - } - - It 'Should resize a VHD which has a different size as intended' { - $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -MaximumSizeBytes 2GB -Ensure 'Present' - Assert-MockCalled -CommandName Resize-VHD -Exactly -Times 1 -Scope It - } - - It 'Should update the parentpath if it is different from intent' { - $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -ParentPath 'c:\boguspath2\server.vhdx' -Ensure 'Present' - Assert-MockCalled -CommandName Set-VHD -Exactly -Times 1 -Scope It - } - } - } - } -} -finally -{ - Invoke-TestCleanup -} +# $script:dscModuleName = 'HyperVDsc' +# $script:dscResourceName = 'DSC_Vhd' + +# function Invoke-TestSetup +# { +# try +# { +# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' +# } +# catch [System.IO.FileNotFoundException] +# { +# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' +# } + +# $script:testEnvironment = Initialize-TestEnvironment ` +# -DSCModuleName $script:dscModuleName ` +# -DSCResourceName $script:dscResourceName ` +# -ResourceType 'Mof' ` +# -TestType 'Unit' + +# # Import the stub functions. +# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +# } + +# function Invoke-TestCleanup +# { +# Restore-TestEnvironment -TestEnvironment $script:testEnvironment +# } + +# Invoke-TestSetup + +# try +# { +# InModuleScope $script:dscResourceName { +# Describe 'DSC_Vhd\Get-TargetResource' { +# Context 'Should stop when Hyper-V module is missing' { +# Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } -MockWith { +# return $false +# } + +# It 'Should throw when the module is missing' { +# { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | +# Should -Throw 'Please ensure that Hyper-V role is installed with its PowerShell module' +# } +# } + +# # 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 -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } + +# Context 'VHD Present' { +# It 'Should return a hashtable with Ensure being Present' { +# Mock -CommandName Get-VHD -MockWith { +# [pscustomobject]@{ +# Path = 'server.vhdx' +# } +# } + +# $getTargetResult = Get-TargetResource -Name 'server' -Path 'c:\boguspath' -Generation 'vhdx' +# $getTargetResult.Ensure | Should -Be 'Present' +# $getTargetResult | Should -BeOfType hashtable +# } +# } + +# Context 'VHD Not Present' { +# It 'Should return a hashtable with Ensure being Absent' { +# Mock -CommandName Get-VHD + +# $getTargetResult = Get-TargetResource -Name 'server' -Path 'c:\boguspath' -Generation 'vhdx' +# $getTargetResult.Ensure | Should -Be 'Absent' +# $getTargetResult | Should -BeOfType hashtable +# } +# } +# } + +# Describe 'DSC_Vhd\GetNameWithExtension' { +# Context 'Name does not have extension' { +# It 'Should return server.vhdx with generation vhdx' { +# GetNameWithExtension -Name 'server' -Generation 'vhdx' | +# Should -Be 'server.vhdx' +# } + +# It 'Should return server.vhd with generation vhd' { +# GetNameWithExtension -Name 'server' -Generation 'vhd' | +# Should -Be 'server.vhd' +# } + +# It 'Should not throw' { +# { GetNameWithExtension -Name 'server' -Generation 'vhd' } | +# Should -Not -throw +# } +# } + +# Context 'Name has extension' { +# It 'Should return server.vhdx with Name server.vhdx and generation vhdx' { +# GetNameWithExtension -Name 'server.vhd' -Generation 'vhd' | +# Should -Be 'server.vhd' +# } + +# It 'Should throw with mismatch with extension from name and generation' { +# { GetNameWithExtension -Name 'server.vhdx' -Generation 'vhd' } | +# Should -Throw 'the extension vhdx on the name does not match the generation vhd' +# } +# } +# } + +# Describe 'DSC_Vhd\Test-TargetResource' { +# # Create an empty function to be able to mock the missing Hyper-V cmdlet +# function Test-VHD +# { + +# } + +# Context 'Should stop when Hyper-V module is missing' { +# Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } -MockWith { +# return $false +# } + +# It 'Should throw when the module is missing' { +# { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | +# Should -Throw 'Please ensure that Hyper-V role is installed with its PowerShell module' +# } +# } + +# # 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 +# } + +# Context 'Parameter validation' { +# It 'Fixed and Dynamic VHDs need MaximumSizeBytes specified' { +# { Test-TargetResource -Name 'server' -Path 'C:\VMs' -Type 'Dynamic' } | +# Should -Throw 'Specify MaximumSizeBytes property for Fixed and Dynamic VHDs.' +# } + +# It 'Parent Path is passed for a non Differencing disk' { +# { Test-TargetResource -Name 'server' -Path 'C:\VMs' -ParentPath 'C:\VMs\Parent' -Type 'Fixed' -MaximumSizeBytes 1GB } | +# Should -Throw 'Parent path is only supported for Differencing disks' +# } + +# It 'Differencing disk needs a Parent Path' { +# { Test-TargetResource -Name 'server' -Path 'C:\VMs' -Type 'Differencing' } | +# Should -Throw 'Differencing requires a parent path' +# } +# } + +# Context 'ParentPath specified' { +# It 'Should throw when ParentPath does not exist' { +# Mock -CommandName Test-Path -MockWith { $false } + +# { Test-TargetResource -Name 'server' -Path 'C:\VMs' -Type 'Differencing' -ParentPath 'c:\boguspath' } | +# Should -Throw 'c:\boguspath does not exists' +# } + +# # "Generation $Generation should match ParentPath extension $($ParentPath.Split('.')[-1])" +# It 'Should throw when file extension and generation have a mismatch' { +# Mock -CommandName Test-Path -MockWith { $true } + +# { Test-TargetResource -Name 'server' -Path 'C:\VMs' -Type 'Differencing' -ParentPath 'c:\boguspath.vhd' -Generation 'Vhdx' } | +# Should -Throw 'Generation Vhdx should match ParentPath extension vhd' +# } +# } + +# Context 'Path does not exist' { +# It 'Should throw when the path does not exist' { +# Mock -CommandName Test-Path -MockWith { $false } + +# { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | +# Should -Throw 'C:\VMs does not exists' +# } +# } + +# Context 'Vhd exists' { +# BeforeEach { +# Mock -CommandName Test-Path -MockWith { $true } +# Mock -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } +# Mock -CommandName Test-VHD -MockWith { $true } +# } + +# It 'Should not throw' { +# { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | +# Should -not -throw +# } + +# It 'Should return a boolean and it should be true' { +# $testResult = Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB +# $testResult | Should -BeOfType bool +# $testResult -eq $true | Should -Be $true +# } +# } + +# Context 'Vhd does not exist' { +# BeforeEach { +# Mock -CommandName Test-Path -MockWith { $true } +# Mock -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } +# Mock -CommandName Test-VHD -MockWith { $false } +# } + +# It 'Should not throw' { +# { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | +# Should -not -throw +# } + +# It 'Should return a boolean and it should be false' { +# $testResult = Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB +# $testResult | Should -BeOfType bool +# $testResult -eq $true | Should -Be $false +# } +# } +# } + +# Describe 'DSC_Vhd\Set-TargetResource' { +# Context 'Ensure is Absent' { +# Mock -CommandName Test-Path -MockWith { $true } +# Mock -CommandName Remove-Item +# Mock -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } + +# It 'Should remove when Ensure is Absent and vhdx exists' { +# $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -Ensure 'Absent' +# Assert-MockCalled -CommandName Remove-Item -Times 1 -Exactly +# } +# } + +# Context 'Ensure is Present' { +# BeforeEach { +# Mock -CommandName Get-VHD -MockWith { +# [pscustomobject]@{ +# Path = 'server.vhdx' +# ParentPath = 'c:\boguspath\server.vhdx' +# Size = 1073741824 +# Type = 'Differencing' +# } +# } + +# Mock -CommandName Set-VHD +# Mock -CommandName Resize-VHD +# Mock -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } +# Mock -CommandName New-VHD +# } + +# It 'Should Create a VHD when Ensure is present and no VHD exists yet for non Differencing disk' { +# Mock -CommandName Get-VHD -MockWith { throw } + +# $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -Ensure 'Present' +# Assert-MockCalled -CommandName New-VHD -Exactly -Times 1 -Scope It +# } + +# It 'Should Create a VHD when Ensure is present and no VHD exists yet for Differencing disk' { +# Mock -CommandName Get-VHD -MockWith { throw } + +# $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -Ensure 'Present' -ParentPath 'c:\boguspath\server.vhdx' -Type 'Differencing' +# Assert-MockCalled -CommandName New-VHD -Exactly -Times 1 -Scope It +# } + +# It 'Should resize a VHD which has a different size as intended' { +# $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -MaximumSizeBytes 2GB -Ensure 'Present' +# Assert-MockCalled -CommandName Resize-VHD -Exactly -Times 1 -Scope It +# } + +# It 'Should update the parentpath if it is different from intent' { +# $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -ParentPath 'c:\boguspath2\server.vhdx' -Ensure 'Present' +# Assert-MockCalled -CommandName Set-VHD -Exactly -Times 1 -Scope It +# } +# } +# } +# } +# } +# finally +# { +# Invoke-TestCleanup +# } diff --git a/tests/Unit/DSC_VMDvdDrive.Tests.ps1 b/tests/Unit/DSC_VMDvdDrive.Tests.ps1 index ecb892f..e13cb29 100644 --- a/tests/Unit/DSC_VMDvdDrive.Tests.ps1 +++ b/tests/Unit/DSC_VMDvdDrive.Tests.ps1 @@ -1,694 +1,694 @@ -$script:dscModuleName = 'HyperVDsc' -$script:dscResourceName = 'DSC_VMDvdDrive' - -function Invoke-TestSetup -{ - try - { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' - } - catch [System.IO.FileNotFoundException] - { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' - } - - $script:testEnvironment = Initialize-TestEnvironment ` - -DSCModuleName $script:dscModuleName ` - -DSCResourceName $script:dscResourceName ` - -ResourceType 'Mof' ` - -TestType 'Unit' - - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -} - -function Invoke-TestCleanup -{ - Restore-TestEnvironment -TestEnvironment $script:testEnvironment -} - -Invoke-TestSetup - -try -{ - InModuleScope $script:dscResourceName { - #region Pester Test Initialization - - $script:VMName = 'HyperVUnitTestsVM' - $script:TestISOPath = 'd:\test\test.iso' - - $script:splatGetDvdDrive = @{ - VMName = $script:VMName - ControllerNumber = 0 - ControllerLocation = 1 - Verbose = $True - } - $script:splatAddDvdDriveNoPath = @{ - VMName = $script:VMName - ControllerNumber = 0 - ControllerLocation = 1 - Path = '' - Ensure = 'Present' - Verbose = $True - } - $script:splatAddDvdDrive = @{ - VMName = $script:VMName - ControllerNumber = 0 - ControllerLocation = 1 - Path = $script:TestISOPath - Ensure = 'Present' - Verbose = $True - } - $script:splatRemoveDvdDrive = @{ - VMName = $script:VMName - ControllerNumber = 0 - ControllerLocation = 1 - Ensure = 'Absent' - Verbose = $True - } - $script:mockGetModule = [pscustomobject] @{ - Name = 'Hyper-V' - } - $script:mockGetVM = [pscustomobject] @{ - Name = $VMName - } - $script:mockGetVMScsiController = [pscustomobject] @{ - VMName = $VMName - } - $script:mockGetVMHardDiskDrive = [pscustomobject] @{ - VMName = $VMName - } - $script:mockNoDvdDrive = @{ - VMName = $script:VMName - ControllerNumber = 0 - ControllerLocation = 1 - Ensure = 'Absent' - } - $script:mockDvdDriveWithPath = @{ - VMName = $script:VMName - ControllerNumber = 0 - ControllerLocation = 1 - Path = $script:TestISOPath - Ensure = 'Present' - } - $script:mockDvdDriveWithDiffPath = @{ - VMName = $script:VMName - ControllerNumber = 0 - ControllerLocation = 1 - Path = 'd:\diff\diff.iso' - Ensure = 'Present' - } - #endregion - - #region function Get-TargetResource - Describe 'DSC_VMDvdDrive\Get-TargetResource' { - Context 'DVD Drive does not exist' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Test-ParameterValid ` - -Verifiable - - Mock ` - -CommandName Get-VMDvdDrive ` - -MockWith {} ` - -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } ` - -Verifiable - - It 'should not throw exception' { - { - $script:resource = Get-TargetResource @script:splatGetDvdDrive - } | Should -Not -throw - } - - It 'should return expected values' { - $script:resource.VMName | Should -Be $script:splatGetDvdDrive.VMName - $script:resource.ControllerNumber | Should -Be $script:splatGetDvdDrive.ControllerNumber - $script:resource.ControllerLocation | Should -Be $script:splatGetDvdDrive.ControllerLocation - $script:resource.Path | Should -BeNullOrEmpty - $script:resource.Ensure | Should -Be 'Absent' - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Test-ParameterValid -Exactly 1 - Assert-MockCalled -CommandName Get-VMDvdDrive -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } - } - } - - Context 'DVD Drive exists, but has empty path' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Test-ParameterValid ` - -Verifiable - - Mock ` - -CommandName Get-VMDvdDrive ` - -MockWith { $script:splatAddDvdDriveNoPath } ` - -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } ` - -Verifiable - - It 'should not throw exception' { - { - $script:resource = Get-TargetResource @script:splatGetDvdDrive - } | Should -Not -throw - } - - It 'should return expected values' { - $script:resource.VMName | Should -Be $script:splatGetDvdDrive.VMName - $script:resource.ControllerNumber | Should -Be $script:splatGetDvdDrive.ControllerNumber - $script:resource.ControllerLocation | Should -Be $script:splatGetDvdDrive.ControllerLocation - $script:resource.Path | Should -BeNullOrEmpty - $script:resource.Ensure | Should -Be 'Present' - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Test-ParameterValid -Exactly 1 - Assert-MockCalled -CommandName Get-VMDvdDrive -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } - } - } - - Context 'DVD Drive exists, and has a test ISO path' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Test-ParameterValid ` - -Verifiable - - Mock ` - -CommandName Get-VMDvdDrive ` - -MockWith { $script:splatAddDvdDrive } ` - -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } ` - -Verifiable - - It 'should not throw exception' { - { - $script:resource = Get-TargetResource @script:splatGetDvdDrive - } | Should -Not -throw - } - - It 'should return expected values' { - $script:resource.VMName | Should -Be $script:splatGetDvdDrive.VMName - $script:resource.ControllerNumber | Should -Be $script:splatGetDvdDrive.ControllerNumber - $script:resource.ControllerLocation | Should -Be $script:splatGetDvdDrive.ControllerLocation - $script:resource.Path | Should -Be $script:TestISOPath - $script:resource.Ensure | Should -Be 'Present' - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Test-ParameterValid -Exactly 1 - Assert-MockCalled -CommandName Get-VMDvdDrive -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } - } - } - } - #endregion - - #region function Set-TargetResource - Describe 'DSC_VMDvdDrive\Set-TargetResource' { - Context 'DVD Drive does not exist but should' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Get-TargetResource ` - -MockWith { $script:mockNoDvdDrive } ` - -Verifiable - - Mock ` - -CommandName Add-VMDvdDrive ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` - -Verifiable - - # Mocks that should not be called - Mock -CommandName Set-VMDvdDrive - Mock -CommandName Remove-VMDvdDrive - - It 'should not throw exception' { - { Set-TargetResource @script:splatAddDvdDriveNoPath } | Should -Not -throw - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 - Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } - Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 0 - Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 0 - } - } - - Context 'DVD Drive does exist and should, path matches' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Get-TargetResource ` - -MockWith { $script:mockDvdDriveWithPath } ` - -Verifiable - - # Mocks that should not be called - Mock -CommandName Add-VMDvdDrive - Mock -CommandName Set-VMDvdDrive - Mock -CommandName Remove-VMDvdDrive - - It 'should not throw exception' { - { Set-TargetResource @script:splatAddDvdDrive } | Should -Not -throw - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 - Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 0 - Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 0 - Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 0 - } - } - - Context 'DVD Drive does exist and should, path does not match' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Get-TargetResource ` - -MockWith { $script:mockDvdDriveWithDiffPath } ` - -Verifiable - - Mock ` - -CommandName Set-VMDvdDrive ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` - -Verifiable - - # Mocks that should not be called - Mock -CommandName Add-VMDvdDrive - Mock -CommandName Remove-VMDvdDrive - - It 'should not throw exception' { - { Set-TargetResource @script:splatAddDvdDrive } | Should -Not -throw - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 - Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 0 - Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } - Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 0 - } - } - - Context 'DVD Drive exists and should not' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Get-TargetResource ` - -MockWith { $script:mockDvdDriveWithPath } ` - -Verifiable - - Mock ` - -CommandName Remove-VMDvdDrive ` - -ParameterFilter { $VMName -eq $script:splatRemoveDvdDrive.VMName } ` - -Verifiable - - # Mocks that should not be called - Mock -CommandName Add-VMDvdDrive - Mock -CommandName Set-VMDvdDrive - - It 'should not throw exception' { - { Set-TargetResource @script:splatRemoveDvdDrive } | Should -Not -throw - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 - Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 0 - Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 0 - Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatRemoveDvdDrive.VMName } - } - } - - Context 'DVD Drive does not exist and should not' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Get-TargetResource ` - -MockWith { $script:mockNoDvdDrive } ` - -Verifiable - - # Mocks that should not be called - Mock -CommandName Add-VMDvdDrive - Mock -CommandName Set-VMDvdDrive - Mock -CommandName Remove-VMDvdDrive - - It 'should not throw exception' { - { Set-TargetResource @script:splatRemoveDvdDrive } | Should -Not -throw - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 - Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 0 - Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 0 - Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 0 - } - } - } - #endregion - - #region function Test-TargetResource - Describe 'DSC_VMDvdDrive\Test-TargetResource' { - Context 'DVD Drive does not exist but should' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Get-TargetResource ` - -MockWith { $script:mockNoDvdDrive } ` - -Verifiable - - It 'should return false' { - Test-TargetResource @script:splatAddDvdDriveNoPath | Should -Be $False - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 - } - } - - Context 'DVD Drive does exist and should, path matches' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Get-TargetResource ` - -MockWith { $script:mockDvdDriveWithPath } ` - -Verifiable - - It 'should return true' { - Test-TargetResource @script:splatAddDvdDrive | Should -Be $True - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 - } - } - - Context 'DVD Drive does exist and should, path does not match' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Get-TargetResource ` - -MockWith { $script:mockDvdDriveWithDiffPath } ` - -Verifiable - - It 'should return false' { - Test-TargetResource @script:splatAddDvdDrive | Should -Be $False - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 - } - } - - Context 'DVD Drive exists and should not' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Get-TargetResource ` - -MockWith { $script:mockDvdDriveWithPath } ` - -Verifiable - - It 'should return false' { - Test-TargetResource @script:splatRemoveDvdDrive | Should -Be $False - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 - } - } - - Context 'DVD Drive does not exist and should not' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Get-TargetResource ` - -MockWith { $script:mockNoDvdDrive } ` - -Verifiable - - It 'should return true' { - Test-TargetResource @script:splatRemoveDvdDrive | Should -Be $True - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 - } - } - } - #endregion - - #region function Test-ParameterValid - Describe 'DSC_VMDvdDrive\Test-ParameterValid' { - Context 'Hyper-V Module is not available' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Get-Module ` - -Verifiable - - # Mocks that should not be called - Mock -CommandName Get-VM - Mock -CommandName Get-VMScsiController - Mock -CommandName Get-VMIdeController - Mock -CommandName Get-VMHardDiskDrive - - It 'should throw exception' { - $errorMessage = $script:localizedData.RoleMissingError -f 'Hyper-V' - - { Test-ParameterValid @script:splatAddDvdDriveNoPath } | Should -Throw $errorMessage - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Get-Module -Exactly 1 - } - } - - Context 'VM does not exist' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Get-Module ` - -MockWith { $script:mockGetModule } ` - -Verifiable - - Mock ` - -CommandName Get-VM ` - -MockWith { throw } ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` - -Verifiable - - # Mocks that should not be called - Mock -CommandName Get-VMScsiController - Mock -CommandName Get-VMIdeController - Mock -CommandName Get-VMHardDiskDrive - - It 'should throw exception' { - { Test-ParameterValid @script:splatAddDvdDriveNoPath } | Should -Throw - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Get-Module -Exactly 1 - Assert-MockCalled -CommandName Get-VM -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } - } - } - - Context 'VM exists, controller does not exist' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Get-Module ` - -MockWith { $script:mockGetModule } ` - -Verifiable - - Mock ` - -CommandName Get-VM ` - -MockWith { $script:mockGetVM } ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` - -Verifiable - - Mock ` - -CommandName Get-VMScsiController ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` - -Verifiable - - Mock ` - -CommandName Get-VMIdeController ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` - -Verifiable - - # Mocks that should not be called - Mock -CommandName Get-VMHardDiskDrive - - It 'should throw exception' { - $errorMessage = $script:localizedData.VMControllerDoesNotExistError -f $script:VMName, 0 - - { Test-ParameterValid @script:splatAddDvdDriveNoPath } | Should -Throw $errorMessage - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Get-Module -Exactly 1 - Assert-MockCalled -CommandName Get-VM -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } - Assert-MockCalled -CommandName Get-VMScsiController -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } - Assert-MockCalled -CommandName Get-VMIdeController -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } - } - } - - Context 'VM exists, SCSI controller exists, HD assigned' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Get-Module ` - -MockWith { $script:mockGetModule } ` - -Verifiable - - Mock ` - -CommandName Get-VM ` - -MockWith { $script:mockGetVM } ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` - -Verifiable - - Mock ` - -CommandName Get-VMScsiController ` - -MockWith { $script:mockGetVMScsiController } ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` - -Verifiable - - Mock ` - -CommandName Get-VMHardDiskDrive ` - -MockWith { $script:mockGetVMHardDiskDrive } ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` - -Verifiable - - # Mocks that should not be called - Mock -CommandName Get-VMIdeController - - It 'should throw exception' { - $errorMessage = $script:localizedData.ControllerConflictError -f $script:VMName, 0, 1 - - { Test-ParameterValid @script:splatAddDvdDriveNoPath } | Should -Throw $errorMessage - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Get-Module -Exactly 1 - Assert-MockCalled -CommandName Get-VM -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } - Assert-MockCalled -CommandName Get-VMScsiController -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } - Assert-MockCalled -CommandName Get-VMHardDiskDrive -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } - } - } - - Context 'VM exists, SCSI controller exists, HD not assigned, Path invalid' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Get-Module ` - -MockWith { $script:mockGetModule } ` - -Verifiable - - Mock ` - -CommandName Get-VM ` - -MockWith { $script:mockGetVM } ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` - -Verifiable - - Mock ` - -CommandName Get-VMScsiController ` - -MockWith { $script:mockGetVMScsiController } ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` - -Verifiable - - Mock ` - -CommandName Get-VMHardDiskDrive ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` - -Verifiable - - Mock ` - -CommandName Test-Path ` - -MockWith { $False } ` - -Verifiable - - # Mocks that should not be called - Mock -CommandName Get-VMIdeController - - It 'should throw exception' { - $errorMessage = $script:localizedData.PathDoesNotExistError -f $script:TestISOPath - - { Test-ParameterValid @script:splatAddDvdDrive } | Should -Throw $errorMessage - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Get-Module -Exactly 1 - Assert-MockCalled -CommandName Get-VM -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } - Assert-MockCalled -CommandName Get-VMScsiController -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } - Assert-MockCalled -CommandName Get-VMHardDiskDrive -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } - Assert-MockCalled -CommandName Test-Path -Exactly 1 - } - } - - Context 'VM exists, SCSI contrller exists, HD not assigned, Path Valid' { - # Verifiable (should be called) mocks - Mock ` - -CommandName Get-Module ` - -MockWith { $script:mockGetModule } ` - -Verifiable - - Mock ` - -CommandName Get-VM ` - -MockWith { $script:mockGetVM } ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` - -Verifiable - - Mock ` - -CommandName Get-VMScsiController ` - -MockWith { $script:mockGetVMScsiController } ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` - -Verifiable - - Mock ` - -CommandName Get-VMHardDiskDrive ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` - -Verifiable - - Mock ` - -CommandName Test-Path ` - -MockWith { $True } ` - -Verifiable - - # Mocks that should not be called - Mock -CommandName Get-VMIdeController - - It 'should not throw exception' { - Test-ParameterValid @script:splatAddDvdDrive | Should -Be $True - } - - It 'all the get mocks should be called' { - Assert-VerifiableMock - Assert-MockCalled -CommandName Get-Module -Exactly 1 - Assert-MockCalled -CommandName Get-VM -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } - Assert-MockCalled -CommandName Get-VMScsiController -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } - Assert-MockCalled -CommandName Get-VMHardDiskDrive -Exactly 1 ` - -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } - Assert-MockCalled -CommandName Test-Path -Exactly 1 - } - } - } - #endregion - } -} -finally -{ - Invoke-TestCleanup -} +# $script:dscModuleName = 'HyperVDsc' +# $script:dscResourceName = 'DSC_VMDvdDrive' + +# function Invoke-TestSetup +# { +# try +# { +# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' +# } +# catch [System.IO.FileNotFoundException] +# { +# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' +# } + +# $script:testEnvironment = Initialize-TestEnvironment ` +# -DSCModuleName $script:dscModuleName ` +# -DSCResourceName $script:dscResourceName ` +# -ResourceType 'Mof' ` +# -TestType 'Unit' + +# # Import the stub functions. +# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +# } + +# function Invoke-TestCleanup +# { +# Restore-TestEnvironment -TestEnvironment $script:testEnvironment +# } + +# Invoke-TestSetup + +# try +# { +# InModuleScope $script:dscResourceName { +# #region Pester Test Initialization + +# $script:VMName = 'HyperVUnitTestsVM' +# $script:TestISOPath = 'd:\test\test.iso' + +# $script:splatGetDvdDrive = @{ +# VMName = $script:VMName +# ControllerNumber = 0 +# ControllerLocation = 1 +# Verbose = $True +# } +# $script:splatAddDvdDriveNoPath = @{ +# VMName = $script:VMName +# ControllerNumber = 0 +# ControllerLocation = 1 +# Path = '' +# Ensure = 'Present' +# Verbose = $True +# } +# $script:splatAddDvdDrive = @{ +# VMName = $script:VMName +# ControllerNumber = 0 +# ControllerLocation = 1 +# Path = $script:TestISOPath +# Ensure = 'Present' +# Verbose = $True +# } +# $script:splatRemoveDvdDrive = @{ +# VMName = $script:VMName +# ControllerNumber = 0 +# ControllerLocation = 1 +# Ensure = 'Absent' +# Verbose = $True +# } +# $script:mockGetModule = [pscustomobject] @{ +# Name = 'Hyper-V' +# } +# $script:mockGetVM = [pscustomobject] @{ +# Name = $VMName +# } +# $script:mockGetVMScsiController = [pscustomobject] @{ +# VMName = $VMName +# } +# $script:mockGetVMHardDiskDrive = [pscustomobject] @{ +# VMName = $VMName +# } +# $script:mockNoDvdDrive = @{ +# VMName = $script:VMName +# ControllerNumber = 0 +# ControllerLocation = 1 +# Ensure = 'Absent' +# } +# $script:mockDvdDriveWithPath = @{ +# VMName = $script:VMName +# ControllerNumber = 0 +# ControllerLocation = 1 +# Path = $script:TestISOPath +# Ensure = 'Present' +# } +# $script:mockDvdDriveWithDiffPath = @{ +# VMName = $script:VMName +# ControllerNumber = 0 +# ControllerLocation = 1 +# Path = 'd:\diff\diff.iso' +# Ensure = 'Present' +# } +# #endregion + +# #region function Get-TargetResource +# Describe 'DSC_VMDvdDrive\Get-TargetResource' { +# Context 'DVD Drive does not exist' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Test-ParameterValid ` +# -Verifiable + +# Mock ` +# -CommandName Get-VMDvdDrive ` +# -MockWith {} ` +# -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } ` +# -Verifiable + +# It 'should not throw exception' { +# { +# $script:resource = Get-TargetResource @script:splatGetDvdDrive +# } | Should -Not -throw +# } + +# It 'should return expected values' { +# $script:resource.VMName | Should -Be $script:splatGetDvdDrive.VMName +# $script:resource.ControllerNumber | Should -Be $script:splatGetDvdDrive.ControllerNumber +# $script:resource.ControllerLocation | Should -Be $script:splatGetDvdDrive.ControllerLocation +# $script:resource.Path | Should -BeNullOrEmpty +# $script:resource.Ensure | Should -Be 'Absent' +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Test-ParameterValid -Exactly 1 +# Assert-MockCalled -CommandName Get-VMDvdDrive -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } +# } +# } + +# Context 'DVD Drive exists, but has empty path' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Test-ParameterValid ` +# -Verifiable + +# Mock ` +# -CommandName Get-VMDvdDrive ` +# -MockWith { $script:splatAddDvdDriveNoPath } ` +# -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } ` +# -Verifiable + +# It 'should not throw exception' { +# { +# $script:resource = Get-TargetResource @script:splatGetDvdDrive +# } | Should -Not -throw +# } + +# It 'should return expected values' { +# $script:resource.VMName | Should -Be $script:splatGetDvdDrive.VMName +# $script:resource.ControllerNumber | Should -Be $script:splatGetDvdDrive.ControllerNumber +# $script:resource.ControllerLocation | Should -Be $script:splatGetDvdDrive.ControllerLocation +# $script:resource.Path | Should -BeNullOrEmpty +# $script:resource.Ensure | Should -Be 'Present' +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Test-ParameterValid -Exactly 1 +# Assert-MockCalled -CommandName Get-VMDvdDrive -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } +# } +# } + +# Context 'DVD Drive exists, and has a test ISO path' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Test-ParameterValid ` +# -Verifiable + +# Mock ` +# -CommandName Get-VMDvdDrive ` +# -MockWith { $script:splatAddDvdDrive } ` +# -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } ` +# -Verifiable + +# It 'should not throw exception' { +# { +# $script:resource = Get-TargetResource @script:splatGetDvdDrive +# } | Should -Not -throw +# } + +# It 'should return expected values' { +# $script:resource.VMName | Should -Be $script:splatGetDvdDrive.VMName +# $script:resource.ControllerNumber | Should -Be $script:splatGetDvdDrive.ControllerNumber +# $script:resource.ControllerLocation | Should -Be $script:splatGetDvdDrive.ControllerLocation +# $script:resource.Path | Should -Be $script:TestISOPath +# $script:resource.Ensure | Should -Be 'Present' +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Test-ParameterValid -Exactly 1 +# Assert-MockCalled -CommandName Get-VMDvdDrive -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } +# } +# } +# } +# #endregion + +# #region function Set-TargetResource +# Describe 'DSC_VMDvdDrive\Set-TargetResource' { +# Context 'DVD Drive does not exist but should' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Get-TargetResource ` +# -MockWith { $script:mockNoDvdDrive } ` +# -Verifiable + +# Mock ` +# -CommandName Add-VMDvdDrive ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` +# -Verifiable + +# # Mocks that should not be called +# Mock -CommandName Set-VMDvdDrive +# Mock -CommandName Remove-VMDvdDrive + +# It 'should not throw exception' { +# { Set-TargetResource @script:splatAddDvdDriveNoPath } | Should -Not -throw +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 +# Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } +# Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 0 +# Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 0 +# } +# } + +# Context 'DVD Drive does exist and should, path matches' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Get-TargetResource ` +# -MockWith { $script:mockDvdDriveWithPath } ` +# -Verifiable + +# # Mocks that should not be called +# Mock -CommandName Add-VMDvdDrive +# Mock -CommandName Set-VMDvdDrive +# Mock -CommandName Remove-VMDvdDrive + +# It 'should not throw exception' { +# { Set-TargetResource @script:splatAddDvdDrive } | Should -Not -throw +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 +# Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 0 +# Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 0 +# Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 0 +# } +# } + +# Context 'DVD Drive does exist and should, path does not match' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Get-TargetResource ` +# -MockWith { $script:mockDvdDriveWithDiffPath } ` +# -Verifiable + +# Mock ` +# -CommandName Set-VMDvdDrive ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` +# -Verifiable + +# # Mocks that should not be called +# Mock -CommandName Add-VMDvdDrive +# Mock -CommandName Remove-VMDvdDrive + +# It 'should not throw exception' { +# { Set-TargetResource @script:splatAddDvdDrive } | Should -Not -throw +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 +# Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 0 +# Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } +# Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 0 +# } +# } + +# Context 'DVD Drive exists and should not' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Get-TargetResource ` +# -MockWith { $script:mockDvdDriveWithPath } ` +# -Verifiable + +# Mock ` +# -CommandName Remove-VMDvdDrive ` +# -ParameterFilter { $VMName -eq $script:splatRemoveDvdDrive.VMName } ` +# -Verifiable + +# # Mocks that should not be called +# Mock -CommandName Add-VMDvdDrive +# Mock -CommandName Set-VMDvdDrive + +# It 'should not throw exception' { +# { Set-TargetResource @script:splatRemoveDvdDrive } | Should -Not -throw +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 +# Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 0 +# Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 0 +# Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatRemoveDvdDrive.VMName } +# } +# } + +# Context 'DVD Drive does not exist and should not' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Get-TargetResource ` +# -MockWith { $script:mockNoDvdDrive } ` +# -Verifiable + +# # Mocks that should not be called +# Mock -CommandName Add-VMDvdDrive +# Mock -CommandName Set-VMDvdDrive +# Mock -CommandName Remove-VMDvdDrive + +# It 'should not throw exception' { +# { Set-TargetResource @script:splatRemoveDvdDrive } | Should -Not -throw +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 +# Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 0 +# Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 0 +# Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 0 +# } +# } +# } +# #endregion + +# #region function Test-TargetResource +# Describe 'DSC_VMDvdDrive\Test-TargetResource' { +# Context 'DVD Drive does not exist but should' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Get-TargetResource ` +# -MockWith { $script:mockNoDvdDrive } ` +# -Verifiable + +# It 'should return false' { +# Test-TargetResource @script:splatAddDvdDriveNoPath | Should -Be $False +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 +# } +# } + +# Context 'DVD Drive does exist and should, path matches' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Get-TargetResource ` +# -MockWith { $script:mockDvdDriveWithPath } ` +# -Verifiable + +# It 'should return true' { +# Test-TargetResource @script:splatAddDvdDrive | Should -Be $True +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 +# } +# } + +# Context 'DVD Drive does exist and should, path does not match' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Get-TargetResource ` +# -MockWith { $script:mockDvdDriveWithDiffPath } ` +# -Verifiable + +# It 'should return false' { +# Test-TargetResource @script:splatAddDvdDrive | Should -Be $False +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 +# } +# } + +# Context 'DVD Drive exists and should not' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Get-TargetResource ` +# -MockWith { $script:mockDvdDriveWithPath } ` +# -Verifiable + +# It 'should return false' { +# Test-TargetResource @script:splatRemoveDvdDrive | Should -Be $False +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 +# } +# } + +# Context 'DVD Drive does not exist and should not' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Get-TargetResource ` +# -MockWith { $script:mockNoDvdDrive } ` +# -Verifiable + +# It 'should return true' { +# Test-TargetResource @script:splatRemoveDvdDrive | Should -Be $True +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 +# } +# } +# } +# #endregion + +# #region function Test-ParameterValid +# Describe 'DSC_VMDvdDrive\Test-ParameterValid' { +# Context 'Hyper-V Module is not available' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Get-Module ` +# -Verifiable + +# # Mocks that should not be called +# Mock -CommandName Get-VM +# Mock -CommandName Get-VMScsiController +# Mock -CommandName Get-VMIdeController +# Mock -CommandName Get-VMHardDiskDrive + +# It 'should throw exception' { +# $errorMessage = $script:localizedData.RoleMissingError -f 'Hyper-V' + +# { Test-ParameterValid @script:splatAddDvdDriveNoPath } | Should -Throw $errorMessage +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Get-Module -Exactly 1 +# } +# } + +# Context 'VM does not exist' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Get-Module ` +# -MockWith { $script:mockGetModule } ` +# -Verifiable + +# Mock ` +# -CommandName Get-VM ` +# -MockWith { throw } ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` +# -Verifiable + +# # Mocks that should not be called +# Mock -CommandName Get-VMScsiController +# Mock -CommandName Get-VMIdeController +# Mock -CommandName Get-VMHardDiskDrive + +# It 'should throw exception' { +# { Test-ParameterValid @script:splatAddDvdDriveNoPath } | Should -Throw +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Get-Module -Exactly 1 +# Assert-MockCalled -CommandName Get-VM -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } +# } +# } + +# Context 'VM exists, controller does not exist' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Get-Module ` +# -MockWith { $script:mockGetModule } ` +# -Verifiable + +# Mock ` +# -CommandName Get-VM ` +# -MockWith { $script:mockGetVM } ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` +# -Verifiable + +# Mock ` +# -CommandName Get-VMScsiController ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` +# -Verifiable + +# Mock ` +# -CommandName Get-VMIdeController ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` +# -Verifiable + +# # Mocks that should not be called +# Mock -CommandName Get-VMHardDiskDrive + +# It 'should throw exception' { +# $errorMessage = $script:localizedData.VMControllerDoesNotExistError -f $script:VMName, 0 + +# { Test-ParameterValid @script:splatAddDvdDriveNoPath } | Should -Throw $errorMessage +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Get-Module -Exactly 1 +# Assert-MockCalled -CommandName Get-VM -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } +# Assert-MockCalled -CommandName Get-VMScsiController -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } +# Assert-MockCalled -CommandName Get-VMIdeController -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } +# } +# } + +# Context 'VM exists, SCSI controller exists, HD assigned' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Get-Module ` +# -MockWith { $script:mockGetModule } ` +# -Verifiable + +# Mock ` +# -CommandName Get-VM ` +# -MockWith { $script:mockGetVM } ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` +# -Verifiable + +# Mock ` +# -CommandName Get-VMScsiController ` +# -MockWith { $script:mockGetVMScsiController } ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` +# -Verifiable + +# Mock ` +# -CommandName Get-VMHardDiskDrive ` +# -MockWith { $script:mockGetVMHardDiskDrive } ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` +# -Verifiable + +# # Mocks that should not be called +# Mock -CommandName Get-VMIdeController + +# It 'should throw exception' { +# $errorMessage = $script:localizedData.ControllerConflictError -f $script:VMName, 0, 1 + +# { Test-ParameterValid @script:splatAddDvdDriveNoPath } | Should -Throw $errorMessage +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Get-Module -Exactly 1 +# Assert-MockCalled -CommandName Get-VM -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } +# Assert-MockCalled -CommandName Get-VMScsiController -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } +# Assert-MockCalled -CommandName Get-VMHardDiskDrive -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } +# } +# } + +# Context 'VM exists, SCSI controller exists, HD not assigned, Path invalid' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Get-Module ` +# -MockWith { $script:mockGetModule } ` +# -Verifiable + +# Mock ` +# -CommandName Get-VM ` +# -MockWith { $script:mockGetVM } ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` +# -Verifiable + +# Mock ` +# -CommandName Get-VMScsiController ` +# -MockWith { $script:mockGetVMScsiController } ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` +# -Verifiable + +# Mock ` +# -CommandName Get-VMHardDiskDrive ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` +# -Verifiable + +# Mock ` +# -CommandName Test-Path ` +# -MockWith { $False } ` +# -Verifiable + +# # Mocks that should not be called +# Mock -CommandName Get-VMIdeController + +# It 'should throw exception' { +# $errorMessage = $script:localizedData.PathDoesNotExistError -f $script:TestISOPath + +# { Test-ParameterValid @script:splatAddDvdDrive } | Should -Throw $errorMessage +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Get-Module -Exactly 1 +# Assert-MockCalled -CommandName Get-VM -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } +# Assert-MockCalled -CommandName Get-VMScsiController -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } +# Assert-MockCalled -CommandName Get-VMHardDiskDrive -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } +# Assert-MockCalled -CommandName Test-Path -Exactly 1 +# } +# } + +# Context 'VM exists, SCSI contrller exists, HD not assigned, Path Valid' { +# # Verifiable (should be called) mocks +# Mock ` +# -CommandName Get-Module ` +# -MockWith { $script:mockGetModule } ` +# -Verifiable + +# Mock ` +# -CommandName Get-VM ` +# -MockWith { $script:mockGetVM } ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` +# -Verifiable + +# Mock ` +# -CommandName Get-VMScsiController ` +# -MockWith { $script:mockGetVMScsiController } ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` +# -Verifiable + +# Mock ` +# -CommandName Get-VMHardDiskDrive ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` +# -Verifiable + +# Mock ` +# -CommandName Test-Path ` +# -MockWith { $True } ` +# -Verifiable + +# # Mocks that should not be called +# Mock -CommandName Get-VMIdeController + +# It 'should not throw exception' { +# Test-ParameterValid @script:splatAddDvdDrive | Should -Be $True +# } + +# It 'all the get mocks should be called' { +# Assert-VerifiableMock +# Assert-MockCalled -CommandName Get-Module -Exactly 1 +# Assert-MockCalled -CommandName Get-VM -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } +# Assert-MockCalled -CommandName Get-VMScsiController -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } +# Assert-MockCalled -CommandName Get-VMHardDiskDrive -Exactly 1 ` +# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } +# Assert-MockCalled -CommandName Test-Path -Exactly 1 +# } +# } +# } +# #endregion +# } +# } +# finally +# { +# Invoke-TestCleanup +# } diff --git a/tests/Unit/DSC_VMHardDiskDrive.Tests.ps1 b/tests/Unit/DSC_VMHardDiskDrive.Tests.ps1 index 60ae4cc..8ca71cd 100644 --- a/tests/Unit/DSC_VMHardDiskDrive.Tests.ps1 +++ b/tests/Unit/DSC_VMHardDiskDrive.Tests.ps1 @@ -1,276 +1,276 @@ -$script:dscModuleName = 'HyperVDsc' -$script:dscResourceName = 'DSC_VMHardDiskDrive' +# $script:dscModuleName = 'HyperVDsc' +# $script:dscResourceName = 'DSC_VMHardDiskDrive' -function Invoke-TestSetup -{ - try - { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' - } - catch [System.IO.FileNotFoundException] - { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' - } +# function Invoke-TestSetup +# { +# try +# { +# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' +# } +# catch [System.IO.FileNotFoundException] +# { +# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' +# } - $script:testEnvironment = Initialize-TestEnvironment ` - -DSCModuleName $script:dscModuleName ` - -DSCResourceName $script:dscResourceName ` - -ResourceType 'Mof' ` - -TestType 'Unit' +# $script:testEnvironment = Initialize-TestEnvironment ` +# -DSCModuleName $script:dscModuleName ` +# -DSCResourceName $script:dscResourceName ` +# -ResourceType 'Mof' ` +# -TestType 'Unit' - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -} +# # Import the stub functions. +# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +# } -function Invoke-TestCleanup -{ - Restore-TestEnvironment -TestEnvironment $script:testEnvironment -} +# function Invoke-TestCleanup +# { +# Restore-TestEnvironment -TestEnvironment $script:testEnvironment +# } -Invoke-TestSetup +# Invoke-TestSetup -try -{ - InModuleScope $script:dscResourceName { +# try +# { +# InModuleScope $script:dscResourceName { - $testVMName = 'UnitTestVM' - $testHardDiskPath = 'TestDrive:\{0}.vhdx' -f $testVMName +# $testVMName = 'UnitTestVM' +# $testHardDiskPath = 'TestDrive:\{0}.vhdx' -f $testVMName - Describe 'DSC_VMHardDiskDrive\Get-TargetResource' { +# Describe 'DSC_VMHardDiskDrive\Get-TargetResource' { - $stubHardDiskDrive = [PSCustomObject] @{ - VMName = $testVMName - Path = $testHardDiskPath - ControllerLocation = 0 - ControllerNumber = 0 - ControllerType = 'SCSI' - } +# $stubHardDiskDrive = [PSCustomObject] @{ +# VMName = $testVMName +# Path = $testHardDiskPath +# ControllerLocation = 0 +# ControllerNumber = 0 +# ControllerType = 'SCSI' +# } - # Guard mocks - Mock -CommandName Assert-Module +# # Guard mocks +# Mock -CommandName Assert-Module - It 'Should return a [System.Collections.Hashtable] object type' { - Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } +# It 'Should return a [System.Collections.Hashtable] object type' { +# Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } - $result = Get-TargetResource -VMName $testVMName -Path $testhardDiskPath +# $result = Get-TargetResource -VMName $testVMName -Path $testhardDiskPath - $result -is [System.Collections.Hashtable] | Should -Be $true - } +# $result -is [System.Collections.Hashtable] | Should -Be $true +# } - It 'Should return "Present" when hard disk is attached' { - Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } +# It 'Should return "Present" when hard disk is attached' { +# Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } - $result = Get-TargetResource -VMName $testVMName -Path $testhardDiskPath +# $result = Get-TargetResource -VMName $testVMName -Path $testhardDiskPath - $result.Ensure | Should -Be 'Present' - } +# $result.Ensure | Should -Be 'Present' +# } - It 'Should return "Absent" when hard disk is not attached' { - Mock -CommandName Get-VMHardDiskDrive +# It 'Should return "Absent" when hard disk is not attached' { +# Mock -CommandName Get-VMHardDiskDrive - $result = Get-TargetResource -VMName $testVMName -Path $testhardDiskPath +# $result = Get-TargetResource -VMName $testVMName -Path $testhardDiskPath - $result.Ensure | Should -Be 'Absent' - } +# $result.Ensure | Should -Be 'Absent' +# } - It 'Should assert Hyper-V module is installed' { - Mock -CommandName Assert-Module - Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } +# It 'Should assert Hyper-V module is installed' { +# Mock -CommandName Assert-Module +# Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } - $null = Get-TargetResource -VMName $testVMName -Path $testhardDiskPath +# $null = Get-TargetResource -VMName $testVMName -Path $testhardDiskPath - Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It - } - } # descrive Get-TargetResource +# Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It +# } +# } # descrive Get-TargetResource - Describe 'DSC_VMHardDiskDrive\Test-TargetResource' { +# Describe 'DSC_VMHardDiskDrive\Test-TargetResource' { - # Guard mocks - Mock -CommandName Assert-Module +# # Guard mocks +# Mock -CommandName Assert-Module - $stubTargetResource = @{ - VMName = $testVMName - Path = $testHardDiskPath - ControllerType = 'SCSI' - ControllerNumber = 0 - ControllerLocation = 0 - Ensure = 'Present' - } +# $stubTargetResource = @{ +# VMName = $testVMName +# Path = $testHardDiskPath +# ControllerType = 'SCSI' +# ControllerNumber = 0 +# ControllerLocation = 0 +# Ensure = 'Present' +# } - It 'Should return a [System.Boolean] object type' { - Mock -CommandName Get-TargetResource { return $stubTargetResource } +# It 'Should return a [System.Boolean] object type' { +# Mock -CommandName Get-TargetResource { return $stubTargetResource } - $result = Test-TargetResource -VMName $testVMName -Path $testHardDiskPath +# $result = Test-TargetResource -VMName $testVMName -Path $testHardDiskPath - $result -is [System.Boolean] | Should -Be $true - } +# $result -is [System.Boolean] | Should -Be $true +# } - $parameterNames = @( - 'ControllerNumber', - 'ControllerLocation' - ) +# $parameterNames = @( +# 'ControllerNumber', +# 'ControllerLocation' +# ) - foreach ($parameterName in $parameterNames) - { - $parameterValue = $stubTargetResource[$parameterName] - $testTargetResourceParams = @{ - VMName = $testVMName - Path = $testHardDiskPath - } +# foreach ($parameterName in $parameterNames) +# { +# $parameterValue = $stubTargetResource[$parameterName] +# $testTargetResourceParams = @{ +# VMName = $testVMName +# Path = $testHardDiskPath +# } - It "Should pass when parameter '$parameterName' is correct" { - # Pass value verbatim so it should always pass first - $testTargetResourceParams[$parameterName] = $parameterValue +# It "Should pass when parameter '$parameterName' is correct" { +# # Pass value verbatim so it should always pass first +# $testTargetResourceParams[$parameterName] = $parameterValue - $result = Test-TargetResource @testTargetResourceParams +# $result = Test-TargetResource @testTargetResourceParams - $result | Should -Be $true - } +# $result | Should -Be $true +# } - It "Should fail when parameter '$parameterName' is incorrect" { - # Add one to cause a test failure - $testTargetResourceParams[$parameterName] = $parameterValue + 1 +# It "Should fail when parameter '$parameterName' is incorrect" { +# # Add one to cause a test failure +# $testTargetResourceParams[$parameterName] = $parameterValue + 1 - $result = Test-TargetResource @testTargetResourceParams +# $result = Test-TargetResource @testTargetResourceParams - $result | Should -Be $false - } - } +# $result | Should -Be $false +# } +# } - It "Should pass when parameter 'ControllerType' is correct" { - $testTargetResourceParams = @{ - VMName = $testVMName - Path = $testHardDiskPath - ControllerType = $stubTargetResource['ControllerType'] - } +# It "Should pass when parameter 'ControllerType' is correct" { +# $testTargetResourceParams = @{ +# VMName = $testVMName +# Path = $testHardDiskPath +# ControllerType = $stubTargetResource['ControllerType'] +# } - $result = Test-TargetResource @testTargetResourceParams +# $result = Test-TargetResource @testTargetResourceParams - $result | Should -Be $true - } +# $result | Should -Be $true +# } - It "Should fail when parameter 'ControllerType' is incorrect" { - $testTargetResourceParams = @{ - VMName = $testVMName - Path = $testHardDiskPath - ControllerType = 'IDE' - } +# It "Should fail when parameter 'ControllerType' is incorrect" { +# $testTargetResourceParams = @{ +# VMName = $testVMName +# Path = $testHardDiskPath +# ControllerType = 'IDE' +# } - $result = Test-TargetResource @testTargetResourceParams +# $result = Test-TargetResource @testTargetResourceParams - $result | Should -Be $false - } +# $result | Should -Be $false +# } - It "Should pass when parameter 'Ensure' is correct" { - $testTargetResourceParams = @{ - VMName = $testVMName - Path = $testHardDiskPath - Ensure = $stubTargetResource['Ensure'] - } +# It "Should pass when parameter 'Ensure' is correct" { +# $testTargetResourceParams = @{ +# VMName = $testVMName +# Path = $testHardDiskPath +# Ensure = $stubTargetResource['Ensure'] +# } - $result = Test-TargetResource @testTargetResourceParams +# $result = Test-TargetResource @testTargetResourceParams - $result | Should -Be $true - } - - It "Should fail when parameter 'Ensure' is incorrect" { - $testTargetResourceParams = @{ - VMName = $testVMName - Path = $testHardDiskPath - Ensure = 'Absent' - } - - $result = Test-TargetResource @testTargetResourceParams - - $result | Should -Be $false - } - - It 'Should throw when IDE controller number 2 is specified' { - $testTargetResourceParams = @{ - VMName = $testVMName - Path = $testHardDiskPath - ControllerType = 'IDE' - ControllerNumber = 2 - } - - { Test-TargetResource @testTargetResourceParams } | Should -Throw 'not valid' - } - - It 'Should throw when IDE controller location 2 is specified' { - $testTargetResourceParams = @{ - VMName = $testVMName - Path = $testHardDiskPath - ControllerType = 'IDE' - ControllerLocation = 2 - } - - { Test-TargetResource @testTargetResourceParams } | Should -Throw 'not valid' - } - } # describe Test-TargetResource - - Describe 'DSC_VMHardDiskDrive\Set-TargetResource' { - # Guard mocks - Mock -CommandName Assert-Module - Mock -CommandName Get-VMHardDiskDrive - Mock -CommandName Set-VMHardDiskDrive - Mock -CommandName Add-VMHardDiskDrive - Mock -CommandName Remove-VMHardDiskDrive - - <# - Create a mock of a the class HardDiskDrive to support piping to - the cmdlet Set-VMHardDiskDrive. - #> - $stubHardDiskDrive = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() - $stubHardDiskDrive.CimSession = New-MockObject -Type CimSession - $stubHardDiskDrive.VMName = $testVMName - $stubHardDiskDrive.Path = $testHardDiskPath - $stubHardDiskDrive.ControllerLocation = 0 - $stubHardDiskDrive.ControllerNumber = 0 - $stubHardDiskDrive.ControllerType = 'SCSI' - - It 'Should assert Hyper-V module is installed' { - Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } - - $null = Set-TargetResource -VMName $testVMName -Path $testHardDiskPath - - Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It - } - - It 'Should update existing hard disk' { - Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } - - $null = Set-TargetResource -VMName $testVMName -Path $testHardDiskPath - - Assert-MockCalled -CommandName Set-VMHardDiskDrive -Scope It - } - - It 'Should add hard disk when is not attached' { - Mock -CommandName Get-VMHardDiskDrive - Mock -CommandName Get-VMHardDiskDrive -ParameterFilter { $PSBoundParameters.ContainsKey('ControllerType') } - - $null = Set-TargetResource -VMName $testVMName -Path $testHardDiskPath - - Assert-MockCalled -CommandName Add-VMHardDiskDrive -Scope It - } - - It 'Should throw when an existing disk is attached to controller/location' { - Mock -CommandName Get-VMHardDiskDrive - Mock -CommandName Get-VMHardDiskDrive -ParameterFilter { $PSBoundParameters.ContainsKey('ControllerType') } { return $stubHardDiskDrive } - - { Set-TargetResource -VMName $testVMName -Path $testHardDiskPath } | Should -Throw 'disk present' - } - - It 'Should remove attached hard disk when Ensure is "Absent"' { - Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } - - $null = Set-TargetResource -VMName $testVMName -Path $testHardDiskPath -Ensure 'Absent' - - Assert-MockCalled -CommandName Remove-VMHardDiskDrive -Scope It - } - } # describe Set-TargetResource - } # InModuleScope -} -finally -{ - Invoke-TestCleanup -} +# $result | Should -Be $true +# } + +# It "Should fail when parameter 'Ensure' is incorrect" { +# $testTargetResourceParams = @{ +# VMName = $testVMName +# Path = $testHardDiskPath +# Ensure = 'Absent' +# } + +# $result = Test-TargetResource @testTargetResourceParams + +# $result | Should -Be $false +# } + +# It 'Should throw when IDE controller number 2 is specified' { +# $testTargetResourceParams = @{ +# VMName = $testVMName +# Path = $testHardDiskPath +# ControllerType = 'IDE' +# ControllerNumber = 2 +# } + +# { Test-TargetResource @testTargetResourceParams } | Should -Throw 'not valid' +# } + +# It 'Should throw when IDE controller location 2 is specified' { +# $testTargetResourceParams = @{ +# VMName = $testVMName +# Path = $testHardDiskPath +# ControllerType = 'IDE' +# ControllerLocation = 2 +# } + +# { Test-TargetResource @testTargetResourceParams } | Should -Throw 'not valid' +# } +# } # describe Test-TargetResource + +# Describe 'DSC_VMHardDiskDrive\Set-TargetResource' { +# # Guard mocks +# Mock -CommandName Assert-Module +# Mock -CommandName Get-VMHardDiskDrive +# Mock -CommandName Set-VMHardDiskDrive +# Mock -CommandName Add-VMHardDiskDrive +# Mock -CommandName Remove-VMHardDiskDrive + +# <# +# Create a mock of a the class HardDiskDrive to support piping to +# the cmdlet Set-VMHardDiskDrive. +# #> +# $stubHardDiskDrive = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() +# $stubHardDiskDrive.CimSession = New-MockObject -Type CimSession +# $stubHardDiskDrive.VMName = $testVMName +# $stubHardDiskDrive.Path = $testHardDiskPath +# $stubHardDiskDrive.ControllerLocation = 0 +# $stubHardDiskDrive.ControllerNumber = 0 +# $stubHardDiskDrive.ControllerType = 'SCSI' + +# It 'Should assert Hyper-V module is installed' { +# Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } + +# $null = Set-TargetResource -VMName $testVMName -Path $testHardDiskPath + +# Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It +# } + +# It 'Should update existing hard disk' { +# Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } + +# $null = Set-TargetResource -VMName $testVMName -Path $testHardDiskPath + +# Assert-MockCalled -CommandName Set-VMHardDiskDrive -Scope It +# } + +# It 'Should add hard disk when is not attached' { +# Mock -CommandName Get-VMHardDiskDrive +# Mock -CommandName Get-VMHardDiskDrive -ParameterFilter { $PSBoundParameters.ContainsKey('ControllerType') } + +# $null = Set-TargetResource -VMName $testVMName -Path $testHardDiskPath + +# Assert-MockCalled -CommandName Add-VMHardDiskDrive -Scope It +# } + +# It 'Should throw when an existing disk is attached to controller/location' { +# Mock -CommandName Get-VMHardDiskDrive +# Mock -CommandName Get-VMHardDiskDrive -ParameterFilter { $PSBoundParameters.ContainsKey('ControllerType') } { return $stubHardDiskDrive } + +# { Set-TargetResource -VMName $testVMName -Path $testHardDiskPath } | Should -Throw 'disk present' +# } + +# It 'Should remove attached hard disk when Ensure is "Absent"' { +# Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } + +# $null = Set-TargetResource -VMName $testVMName -Path $testHardDiskPath -Ensure 'Absent' + +# Assert-MockCalled -CommandName Remove-VMHardDiskDrive -Scope It +# } +# } # describe Set-TargetResource +# } # InModuleScope +# } +# finally +# { +# Invoke-TestCleanup +# } diff --git a/tests/Unit/DSC_VMHost.Tests.ps1 b/tests/Unit/DSC_VMHost.Tests.ps1 index a53fef9..d8099bb 100644 --- a/tests/Unit/DSC_VMHost.Tests.ps1 +++ b/tests/Unit/DSC_VMHost.Tests.ps1 @@ -1,361 +1,361 @@ -$script:dscModuleName = 'HyperVDsc' -$script:dscResourceName = 'DSC_VMHost' - -function Invoke-TestSetup -{ - try - { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' - } - catch [System.IO.FileNotFoundException] - { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' - } - - $script:testEnvironment = Initialize-TestEnvironment ` - -DSCModuleName $script:dscModuleName ` - -DSCResourceName $script:dscResourceName ` - -ResourceType 'Mof' ` - -TestType 'Unit' - - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -} - -function Invoke-TestCleanup -{ - Restore-TestEnvironment -TestEnvironment $script:testEnvironment -} - -Invoke-TestSetup - -try -{ - InModuleScope $script:dscResourceName { - - $testVMName = 'UnitTestVM' - - Describe 'DSC_VMHost\Get-TargetResource' { - $fakeVMHost = @{ - ResourceMeteringSaveInterval = 60 - } - - It 'Should return a [System.Collections.Hashtable] object type' { - Mock -CommandName Assert-Module - Mock -CommandName Get-VMHost { return $fakeVMHost } - - $result = Get-TargetResource -IsSingleInstance 'Yes' - - $result -is [System.Collections.Hashtable] | Should -Be $true - } - - It 'Should assert Hyper-V module is installed' { - Mock -CommandName Assert-Module - Mock -CommandName Get-VMHost { return $fakeVMHost } - - $result = Get-TargetResource -IsSingleInstance 'Yes' - - Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It - } - - } # describe Get-TargetResource - - Describe 'DSC_VMHost\Test-TargetResource' { - - # Guard mocks - Mock -CommandName Assert-Module - - $fakeTargetResource = @{ - IsSingleInstance = 'Yes' - EnableEnhancedSessionMode = $true - FibreChannelWwnn = 'C003FF0000FFFF00' - FibreChannelWwpnMaximum = 'C003FFFBEAE1FFFF' - FibreChannelWwpnMinimum = 'C003FFFBEAE10000' - MacAddressMinimum = '00155D327500' - MacAddressMaximum = '00155D3275FF' - MaximumStorageMigrations = 2 - MaximumVirtualMachineMigrations = 2 - NumaSpanningEnabled = $true - ResourceMeteringSaveIntervalMinute = 60 - UseAnyNetworkForMigration = $false - VirtualMachinePath ='C:\ProgramData\Microsoft\Windows\Hyper-V' - VirtualMachineMigrationAuthenticationType = 'CredSSP' - VirtualMachineMigrationPerformanceOption = 'TCPIP' - VirtualHardDiskPath = 'C:\Users\Public\Documents\Hyper-V\Virtual Hard Disks' - VirtualMachineMigrationEnabled = $true - } - - It 'Should return a [System.Boolean] object type' { - Mock -CommandName Get-TargetResource { return $fakeTargetResource } - - $testTargetResourceParams = @{ - IsSingleInstance = 'Yes' - EnableEnhancedSessionMode = $fakeTargetResource.EnableEnhancedSessionMode - VirtualMachineMigrationEnabled = $fakeTargetResource.VirtualMachineMigrationEnabled - } - $result = Test-TargetResource @testTargetResourceParams - - $result -is [System.Boolean] | Should -Be $true - } - - It 'Should assert Hyper-V module is installed' { - Mock -CommandName Get-TargetResource { return $fakeTargetResource } - - $testTargetResourceParams = @{ - IsSingleInstance = 'Yes' - EnableEnhancedSessionMode = $fakeTargetResource.EnableEnhancedSessionMode - } - $result = Test-TargetResource @testTargetResourceParams - - Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It - } - - $parameterNames = @( - 'EnableEnhancedSessionMode', - 'FibreChannelWwnn', - 'FibreChannelWwpnMaximum', - 'FibreChannelWwpnMinimum', - 'MacAddressMaximum', - 'MacAddressMinimum', - 'MaximumStorageMigrations', - 'MaximumVirtualMachineMigrations', - 'NumaSpanningEnabled', - 'ResourceMeteringSaveIntervalMinute', - 'UseAnyNetworkForMigration', - 'VirtualHardDiskPath', - 'VirtualMachinePath', - 'VirtualMachineMigrationEnabled' - ) - - # Test each individual parameter value separately - foreach ($parameterName in $parameterNames) - { - $parameterValue = $fakeTargetResource[$parameterName] - $testTargetResourceParams = @{ - IsSingleInstance = 'Yes' - } - - # Pass value verbatim so it should always pass first - It "Should pass when parameter '$parameterName' is correct" { - $testTargetResourceParams[$parameterName] = $parameterValue - - $result = Test-TargetResource @testTargetResourceParams - - $result | Should -Be $true - } - - if ($parameterValue -is [System.Boolean]) - { - # Invert parameter value to cause a test failure - $testTargetResourceParams[$parameterName] = -not $parameterValue - } - elseif ($parameterValue -is [System.String]) - { - # Repeat string to cause a test failure - $testTargetResourceParams[$parameterName] = "$parameterValue$parameterValue" - } - elseif ($parameterValue -is [System.Int32] -or $parameterValue -is [System.Int64]) - { - # Add one to cause a test failure - $testTargetResourceParams[$parameterName] = $parameterValue + 1 - } - - It "Should fail when parameter '$parameterName' is incorrect" { - $result = Test-TargetResource @testTargetResourceParams - - $result | Should -Be $false - } - } - - It "Should pass when parameter is correct" -TestCases @( - @{ - Parameter = 'VirtualMachineMigrationAuthenticationType' - Value = $fakeTargetResource.VirtualMachineMigrationAuthenticationType - Expected = $true - } - @{ - Parameter = 'VirtualMachineMigrationPerformanceOption' - Value = $fakeTargetResource.VirtualMachineMigrationPerformanceOption - Expected = $true - } - @{ - Parameter = 'VirtualMachineMigrationEnabled' - Value = $fakeTargetResource.VirtualMachineMigrationEnabled - Expected = $true - } - ) -Test { - param - ( - [Parameter()] - [System.String] - $Parameter, - - [Parameter()] - [System.Object] - $Value, - - [Parameter()] - [System.Boolean] - $Expected - ) - - $testTargetResourceParams = @{ - IsSingleInstance = 'Yes' - $Parameter = $Value - } - - $result = Test-TargetResource @testTargetResourceParams | Should -Be $Expected - } - - It "Should fail when parameter is incorrect" -TestCases @( - @{ - Parameter = 'VirtualMachineMigrationAuthenticationType' - Value = 'Kerberos' - Expected = $false - } - @{ - Parameter = 'VirtualMachineMigrationPerformanceOption' - Value = 'Compression' - Expected = $false - } - @{ - Parameter = 'VirtualMachineMigrationEnabled' - Value = $true - Expected = $true - } - ) -Test { - param - ( - [Parameter()] - [System.String] - $Parameter, - - [Parameter()] - [System.Object] - $Value, - - [Parameter()] - [System.Boolean] - $Expected - ) - - $testTargetResourceParams = @{ - IsSingleInstance = 'Yes' - $Parameter = $Value - } - - $result = Test-TargetResource @testTargetResourceParams | Should -Be $Expected - } - - } # describe Test-TargetResource - - Describe 'DSC_VMHost\Set-TargetResource' { - # Guard mocks - Mock -CommandName Assert-Module - Mock -CommandName Get-VMHost - Mock -CommandName Set-VMHost - Mock -CommandName Enable-VMMigration - Mock -CommandName Disable-VMMigration - - It 'Should assert Hyper-V module is installed' { - $setTargetResourceParams = @{ - IsSingleInstance = 'Yes' - } - - $result = Set-TargetResource @setTargetResourceParams - - Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It - } - - It 'Should call "Set-VMHost" with [System.TimeSpan] object when "ResourceMeteringSaveIntervalMinute" specified' { - $setTargetResourceParams = @{ - IsSingleInstance = 'Yes' - ResourceMeteringSaveIntervalMinute = 60 - } - - $result = Set-TargetResource @setTargetResourceParams - - Assert-MockCalled -CommandName Set-VMHost -ParameterFilter { $ResourceMeteringSaveInterval -is [System.TimeSpan] } - } - - It 'Should call "Enable-VMMigration" when "VirtualMachineMigrationEnabled" is set to true and computer is domain joined' { - Mock -CommandName 'Get-CimInstance' -MockWith { - [pscustomobject] @{ - PartOfDomain = $true - } - } - - Mock -CommandName 'Write-Error' - - $setTargetResourceParams = @{ - IsSingleInstance = 'Yes' - VirtualMachineMigrationEnabled = $true - } - - $result = Set-TargetResource @setTargetResourceParams - Assert-MockCalled -CommandName Write-Error -Times 0 -Exactly -Scope it - Assert-MockCalled -CommandName Enable-VMMigration -Times 1 -Exactly -Scope it - Assert-MockCalled -CommandName Disable-VMMigration -Times 0 -Exactly -Scope it - } - - It 'Should not call "Enable-VMMigration" and should throw when "VirtualMachineMigrationEnabled" is set to true and computer is not domain joined' { - Mock -CommandName 'Get-CimInstance' -MockWith { - [pscustomobject] @{ - PartOfDomain = $false - } - } - - $setTargetResourceParams = @{ - IsSingleInstance = 'Yes' - VirtualMachineMigrationEnabled = $true - } - - { Set-TargetResource @setTargetResourceParams } | Should -Throw - Assert-MockCalled -CommandName Enable-VMMigration -Times 0 -Exactly -Scope it - Assert-MockCalled -CommandName Disable-VMMigration -Times 0 -Exactly -Scope it - } - - It 'Should call "Disable-VMMigration" when "VirtualMachineMigrationEnabled" is set to false' { - $setTargetResourceParams = @{ - IsSingleInstance = 'Yes' - VirtualMachineMigrationEnabled = $false - } - - $result = Set-TargetResource @setTargetResourceParams - Assert-MockCalled -CommandName Enable-VMMigration -Times 0 -Exactly -Scope it - Assert-MockCalled -CommandName Disable-VMMigration -Times 1 -Exactly -Scope it - } - - It 'Should not call "Disable-VMMigration" or "Enable-VMMigration" when "VirtualMachineMigrationEnabled" is not set' { - $setTargetResourceParams = @{ - IsSingleInstance = 'Yes' - } - - $result = Set-TargetResource @setTargetResourceParams - - Assert-MockCalled -CommandName Enable-VMMigration -Times 0 -Exactly -Scope it - Assert-MockCalled -CommandName Disable-VMMigration -Times 0 -Exactly -Scope it - } - - It 'Should not call "Set-VMHost" when only "VirtualMachineMigrationEnabled" is set' { - $setTargetResourceParams = @{ - IsSingleInstance = 'Yes' - VirtualMachineMigrationEnabled = $false - Verbose = $true - } - - $result = Set-TargetResource @setTargetResourceParams - - Assert-MockCalled -CommandName Enable-VMMigration -Times 0 -Exactly -Scope it - Assert-MockCalled -CommandName Disable-VMMigration -Times 1 -Exactly -Scope it - Assert-MockCalled -CommandName Set-VMHost -Times 0 -Exactly -Scope it - } - - } # describe Set-TargetResource - - } # InModuleScope -} -finally -{ - Invoke-TestCleanup -} +# $script:dscModuleName = 'HyperVDsc' +# $script:dscResourceName = 'DSC_VMHost' + +# function Invoke-TestSetup +# { +# try +# { +# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' +# } +# catch [System.IO.FileNotFoundException] +# { +# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' +# } + +# $script:testEnvironment = Initialize-TestEnvironment ` +# -DSCModuleName $script:dscModuleName ` +# -DSCResourceName $script:dscResourceName ` +# -ResourceType 'Mof' ` +# -TestType 'Unit' + +# # Import the stub functions. +# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +# } + +# function Invoke-TestCleanup +# { +# Restore-TestEnvironment -TestEnvironment $script:testEnvironment +# } + +# Invoke-TestSetup + +# try +# { +# InModuleScope $script:dscResourceName { + +# $testVMName = 'UnitTestVM' + +# Describe 'DSC_VMHost\Get-TargetResource' { +# $fakeVMHost = @{ +# ResourceMeteringSaveInterval = 60 +# } + +# It 'Should return a [System.Collections.Hashtable] object type' { +# Mock -CommandName Assert-Module +# Mock -CommandName Get-VMHost { return $fakeVMHost } + +# $result = Get-TargetResource -IsSingleInstance 'Yes' + +# $result -is [System.Collections.Hashtable] | Should -Be $true +# } + +# It 'Should assert Hyper-V module is installed' { +# Mock -CommandName Assert-Module +# Mock -CommandName Get-VMHost { return $fakeVMHost } + +# $result = Get-TargetResource -IsSingleInstance 'Yes' + +# Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It +# } + +# } # describe Get-TargetResource + +# Describe 'DSC_VMHost\Test-TargetResource' { + +# # Guard mocks +# Mock -CommandName Assert-Module + +# $fakeTargetResource = @{ +# IsSingleInstance = 'Yes' +# EnableEnhancedSessionMode = $true +# FibreChannelWwnn = 'C003FF0000FFFF00' +# FibreChannelWwpnMaximum = 'C003FFFBEAE1FFFF' +# FibreChannelWwpnMinimum = 'C003FFFBEAE10000' +# MacAddressMinimum = '00155D327500' +# MacAddressMaximum = '00155D3275FF' +# MaximumStorageMigrations = 2 +# MaximumVirtualMachineMigrations = 2 +# NumaSpanningEnabled = $true +# ResourceMeteringSaveIntervalMinute = 60 +# UseAnyNetworkForMigration = $false +# VirtualMachinePath ='C:\ProgramData\Microsoft\Windows\Hyper-V' +# VirtualMachineMigrationAuthenticationType = 'CredSSP' +# VirtualMachineMigrationPerformanceOption = 'TCPIP' +# VirtualHardDiskPath = 'C:\Users\Public\Documents\Hyper-V\Virtual Hard Disks' +# VirtualMachineMigrationEnabled = $true +# } + +# It 'Should return a [System.Boolean] object type' { +# Mock -CommandName Get-TargetResource { return $fakeTargetResource } + +# $testTargetResourceParams = @{ +# IsSingleInstance = 'Yes' +# EnableEnhancedSessionMode = $fakeTargetResource.EnableEnhancedSessionMode +# VirtualMachineMigrationEnabled = $fakeTargetResource.VirtualMachineMigrationEnabled +# } +# $result = Test-TargetResource @testTargetResourceParams + +# $result -is [System.Boolean] | Should -Be $true +# } + +# It 'Should assert Hyper-V module is installed' { +# Mock -CommandName Get-TargetResource { return $fakeTargetResource } + +# $testTargetResourceParams = @{ +# IsSingleInstance = 'Yes' +# EnableEnhancedSessionMode = $fakeTargetResource.EnableEnhancedSessionMode +# } +# $result = Test-TargetResource @testTargetResourceParams + +# Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It +# } + +# $parameterNames = @( +# 'EnableEnhancedSessionMode', +# 'FibreChannelWwnn', +# 'FibreChannelWwpnMaximum', +# 'FibreChannelWwpnMinimum', +# 'MacAddressMaximum', +# 'MacAddressMinimum', +# 'MaximumStorageMigrations', +# 'MaximumVirtualMachineMigrations', +# 'NumaSpanningEnabled', +# 'ResourceMeteringSaveIntervalMinute', +# 'UseAnyNetworkForMigration', +# 'VirtualHardDiskPath', +# 'VirtualMachinePath', +# 'VirtualMachineMigrationEnabled' +# ) + +# # Test each individual parameter value separately +# foreach ($parameterName in $parameterNames) +# { +# $parameterValue = $fakeTargetResource[$parameterName] +# $testTargetResourceParams = @{ +# IsSingleInstance = 'Yes' +# } + +# # Pass value verbatim so it should always pass first +# It "Should pass when parameter '$parameterName' is correct" { +# $testTargetResourceParams[$parameterName] = $parameterValue + +# $result = Test-TargetResource @testTargetResourceParams + +# $result | Should -Be $true +# } + +# if ($parameterValue -is [System.Boolean]) +# { +# # Invert parameter value to cause a test failure +# $testTargetResourceParams[$parameterName] = -not $parameterValue +# } +# elseif ($parameterValue -is [System.String]) +# { +# # Repeat string to cause a test failure +# $testTargetResourceParams[$parameterName] = "$parameterValue$parameterValue" +# } +# elseif ($parameterValue -is [System.Int32] -or $parameterValue -is [System.Int64]) +# { +# # Add one to cause a test failure +# $testTargetResourceParams[$parameterName] = $parameterValue + 1 +# } + +# It "Should fail when parameter '$parameterName' is incorrect" { +# $result = Test-TargetResource @testTargetResourceParams + +# $result | Should -Be $false +# } +# } + +# It "Should pass when parameter is correct" -TestCases @( +# @{ +# Parameter = 'VirtualMachineMigrationAuthenticationType' +# Value = $fakeTargetResource.VirtualMachineMigrationAuthenticationType +# Expected = $true +# } +# @{ +# Parameter = 'VirtualMachineMigrationPerformanceOption' +# Value = $fakeTargetResource.VirtualMachineMigrationPerformanceOption +# Expected = $true +# } +# @{ +# Parameter = 'VirtualMachineMigrationEnabled' +# Value = $fakeTargetResource.VirtualMachineMigrationEnabled +# Expected = $true +# } +# ) -Test { +# param +# ( +# [Parameter()] +# [System.String] +# $Parameter, + +# [Parameter()] +# [System.Object] +# $Value, + +# [Parameter()] +# [System.Boolean] +# $Expected +# ) + +# $testTargetResourceParams = @{ +# IsSingleInstance = 'Yes' +# $Parameter = $Value +# } + +# $result = Test-TargetResource @testTargetResourceParams | Should -Be $Expected +# } + +# It "Should fail when parameter is incorrect" -TestCases @( +# @{ +# Parameter = 'VirtualMachineMigrationAuthenticationType' +# Value = 'Kerberos' +# Expected = $false +# } +# @{ +# Parameter = 'VirtualMachineMigrationPerformanceOption' +# Value = 'Compression' +# Expected = $false +# } +# @{ +# Parameter = 'VirtualMachineMigrationEnabled' +# Value = $true +# Expected = $true +# } +# ) -Test { +# param +# ( +# [Parameter()] +# [System.String] +# $Parameter, + +# [Parameter()] +# [System.Object] +# $Value, + +# [Parameter()] +# [System.Boolean] +# $Expected +# ) + +# $testTargetResourceParams = @{ +# IsSingleInstance = 'Yes' +# $Parameter = $Value +# } + +# $result = Test-TargetResource @testTargetResourceParams | Should -Be $Expected +# } + +# } # describe Test-TargetResource + +# Describe 'DSC_VMHost\Set-TargetResource' { +# # Guard mocks +# Mock -CommandName Assert-Module +# Mock -CommandName Get-VMHost +# Mock -CommandName Set-VMHost +# Mock -CommandName Enable-VMMigration +# Mock -CommandName Disable-VMMigration + +# It 'Should assert Hyper-V module is installed' { +# $setTargetResourceParams = @{ +# IsSingleInstance = 'Yes' +# } + +# $result = Set-TargetResource @setTargetResourceParams + +# Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It +# } + +# It 'Should call "Set-VMHost" with [System.TimeSpan] object when "ResourceMeteringSaveIntervalMinute" specified' { +# $setTargetResourceParams = @{ +# IsSingleInstance = 'Yes' +# ResourceMeteringSaveIntervalMinute = 60 +# } + +# $result = Set-TargetResource @setTargetResourceParams + +# Assert-MockCalled -CommandName Set-VMHost -ParameterFilter { $ResourceMeteringSaveInterval -is [System.TimeSpan] } +# } + +# It 'Should call "Enable-VMMigration" when "VirtualMachineMigrationEnabled" is set to true and computer is domain joined' { +# Mock -CommandName 'Get-CimInstance' -MockWith { +# [pscustomobject] @{ +# PartOfDomain = $true +# } +# } + +# Mock -CommandName 'Write-Error' + +# $setTargetResourceParams = @{ +# IsSingleInstance = 'Yes' +# VirtualMachineMigrationEnabled = $true +# } + +# $result = Set-TargetResource @setTargetResourceParams +# Assert-MockCalled -CommandName Write-Error -Times 0 -Exactly -Scope it +# Assert-MockCalled -CommandName Enable-VMMigration -Times 1 -Exactly -Scope it +# Assert-MockCalled -CommandName Disable-VMMigration -Times 0 -Exactly -Scope it +# } + +# It 'Should not call "Enable-VMMigration" and should throw when "VirtualMachineMigrationEnabled" is set to true and computer is not domain joined' { +# Mock -CommandName 'Get-CimInstance' -MockWith { +# [pscustomobject] @{ +# PartOfDomain = $false +# } +# } + +# $setTargetResourceParams = @{ +# IsSingleInstance = 'Yes' +# VirtualMachineMigrationEnabled = $true +# } + +# { Set-TargetResource @setTargetResourceParams } | Should -Throw +# Assert-MockCalled -CommandName Enable-VMMigration -Times 0 -Exactly -Scope it +# Assert-MockCalled -CommandName Disable-VMMigration -Times 0 -Exactly -Scope it +# } + +# It 'Should call "Disable-VMMigration" when "VirtualMachineMigrationEnabled" is set to false' { +# $setTargetResourceParams = @{ +# IsSingleInstance = 'Yes' +# VirtualMachineMigrationEnabled = $false +# } + +# $result = Set-TargetResource @setTargetResourceParams +# Assert-MockCalled -CommandName Enable-VMMigration -Times 0 -Exactly -Scope it +# Assert-MockCalled -CommandName Disable-VMMigration -Times 1 -Exactly -Scope it +# } + +# It 'Should not call "Disable-VMMigration" or "Enable-VMMigration" when "VirtualMachineMigrationEnabled" is not set' { +# $setTargetResourceParams = @{ +# IsSingleInstance = 'Yes' +# } + +# $result = Set-TargetResource @setTargetResourceParams + +# Assert-MockCalled -CommandName Enable-VMMigration -Times 0 -Exactly -Scope it +# Assert-MockCalled -CommandName Disable-VMMigration -Times 0 -Exactly -Scope it +# } + +# It 'Should not call "Set-VMHost" when only "VirtualMachineMigrationEnabled" is set' { +# $setTargetResourceParams = @{ +# IsSingleInstance = 'Yes' +# VirtualMachineMigrationEnabled = $false +# Verbose = $true +# } + +# $result = Set-TargetResource @setTargetResourceParams + +# Assert-MockCalled -CommandName Enable-VMMigration -Times 0 -Exactly -Scope it +# Assert-MockCalled -CommandName Disable-VMMigration -Times 1 -Exactly -Scope it +# Assert-MockCalled -CommandName Set-VMHost -Times 0 -Exactly -Scope it +# } + +# } # describe Set-TargetResource + +# } # InModuleScope +# } +# finally +# { +# Invoke-TestCleanup +# } diff --git a/tests/Unit/DSC_VMHyperV.Tests.ps1 b/tests/Unit/DSC_VMHyperV.Tests.ps1 index 13097b0..a789c33 100644 --- a/tests/Unit/DSC_VMHyperV.Tests.ps1 +++ b/tests/Unit/DSC_VMHyperV.Tests.ps1 @@ -1,964 +1,964 @@ -$script:dscModuleName = 'HyperVDsc' -$script:dscResourceName = 'DSC_VMHyperV' - -function Invoke-TestSetup -{ - try - { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' - } - catch [System.IO.FileNotFoundException] - { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' - } - - $script:testEnvironment = Initialize-TestEnvironment ` - -DSCModuleName $script:dscModuleName ` - -DSCResourceName $script:dscResourceName ` - -ResourceType 'Mof' ` - -TestType 'Unit' - - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -} - -function Invoke-TestCleanup -{ - Restore-TestEnvironment -TestEnvironment $script:testEnvironment -} - -Invoke-TestSetup - -try -{ - InModuleScope $script:dscResourceName { - Describe 'xVMHyper-V' { - $null = New-Item -Path 'TestDrive:\TestVM.vhdx' -ItemType File - $null = New-Item -Path 'TestDrive:\TestVM.vhd' -ItemType File - - $stubVhdxDisk = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() - $stubVhdxDisk.Path = 'TestDrive:\TestVM.vhdx' - - $stubVhdDisk = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() - $stubVhdDisk.Path = 'TestDrive:\TestVM.vhd' - - $studVhdxDiskSnapshot = New-Item -Path "TestDrive:\TestVM_D0145678-1576-4435-AB18-9F000C1C17D0.avhdx" -ItemType File - $StubVMConfig = New-Item -Path 'TestDrive:\TestVM.xml' -ItemType File - - # Mock the class VMNetworkAdapter to support piping to cmdlet Connect-VMNetworkAdapter - $stubNIC1 = [Microsoft.HyperV.PowerShell.VMNetworkAdapter]::CreateTypeInstance() - $stubNIC1.SwitchName = 'Test Switch 1' - $stubNIC1.MacAddress = 'AA-BB-CC-DD-EE-FF' - $stubNIC1.IpAddresses = @('192.168.0.1', '10.0.0.1') - - # Mock the class VMNetworkAdapter to support piping to cmdlet Connect-VMNetworkAdapter - $stubNIC2 = [Microsoft.HyperV.PowerShell.VMNetworkAdapter]::CreateTypeInstance() - $stubNIC2.SwitchName = 'Test Switch 2' - $stubNIC2.MacAddress = 'AA-BB-CC-DD-EE-FE' - $stubNIC2.IpAddresses = @('192.168.1.1') - - $mockVmGuid = [System.Guid]::NewGuid().ToString() - - Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'RunningVM' } -MockWith { - $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() - $stubVM.Name = 'RunningVM' - $stubVM.HardDrives = @( - $stubVhdxDisk, - $stubVhdDisk - ) - $stubVM.Path = $StubVMConfig.FullPath - $stubVM.Generation = 1 - $stubVM.MemoryStartup = 512MB - $stubVM.MemoryMinimum = 128MB - $stubVM.MemoryMaximum = 4096MB - $stubVM.ProcessorCount = 1 - $stubVM.ID = $mockVmGuid - $stubVM.CPUUsage = 10 - $stubVM.MemoryAssigned = 512MB - $stubVM.Uptime = New-TimeSpan -Hours 12 - $stubVM.CreationTime = (Get-Date).AddHours(-12) - $stubVM.DynamicMemoryEnabled = $true - $stubVM.Notes = '' - $stubVM.State = 'Running' - $stubVM.NetworkAdapters = @( - $stubNIC1, - $stubNIC2 - ) - - return $stubVM - } - - Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'StoppedVM' } -MockWith { - $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() - $stubVM.Name = 'StoppedVM' - $stubVM.HardDrives = @( - $stubVhdxDisk, - $stubVhdDisk - ) - $stubVM.Path = $StubVMConfig.FullPath - $stubVM.Generation = 1 - $stubVM.MemoryStartup = 512MB - $stubVM.MemoryMinimum = 128MB - $stubVM.MemoryMaximum = 4096MB - $stubVM.ProcessorCount = 1 - $stubVM.ID = $mockVmGuid - $stubVM.CPUUsage = 10 - $stubVM.MemoryAssigned = 512MB - $stubVM.Uptime = New-TimeSpan -Hours 12 - $stubVM.CreationTime = (Get-Date).AddHours(-12) - $stubVM.DynamicMemoryEnabled = $true - $stubVM.Notes = '' - $stubVM.State = 'Off' - $stubVM.NetworkAdapters = @( - $stubNIC1, - $stubNIC2 - ) - - return $stubVM - } - - Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'PausedVM' } -MockWith { - $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() - $stubVM.Name = 'PausedVM' - $stubVM.HardDrives = @( - $stubVhdxDisk, - $stubVhdDisk - ) - $stubVM.Path = $StubVMConfig.FullPath - $stubVM.Generation = 1 - $stubVM.MemoryStartup = 512MB - $stubVM.MemoryMinimum = 128MB - $stubVM.MemoryMaximum = 4096MB - $stubVM.ProcessorCount = 1 - $stubVM.ID = $mockVmGuid - $stubVM.CPUUsage = 10 - $stubVM.MemoryAssigned = 512MB - $stubVM.Uptime = New-TimeSpan -Hours 12 - $stubVM.CreationTime = (Get-Date).AddHours(-12) - $stubVM.DynamicMemoryEnabled = $true - $stubVM.Notes = '' - $stubVM.State = 'Paused' - $stubVM.NetworkAdapters = @( - $stubNIC1, - $stubNIC2 - ) - - return $stubVM - } - - Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'NonexistentVM' } -MockWith { - Write-Error 'VM not found.' - } - - Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'DuplicateVM' } -MockWith { - $stubVM1 = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() - $stubVM1.Name = 'DuplicateVM' - $stubVM1.HardDrives = @( - $stubVhdxDisk, - $stubVhdDisk - ) - $stubVM1.Path = $StubVMConfig.FullPath - $stubVM1.Generation = 1 - $stubVM1.MemoryStartup = 512MB - $stubVM1.MemoryMinimum = 128MB - $stubVM1.MemoryMaximum = 4096MB - $stubVM1.ProcessorCount = 1 - $stubVM1.ID = $mockVmGuid - $stubVM1.CPUUsage = 10 - $stubVM1.MemoryAssigned = 512MB - $stubVM1.Uptime = New-TimeSpan -Hours 12 - $stubVM1.CreationTime = (Get-Date).AddHours(-12) - $stubVM1.DynamicMemoryEnabled = $true - $stubVM1.Notes = '' - $stubVM1.State = 'Off' - $stubVM1.NetworkAdapters = @( - $stubNIC1, - $stubNIC2 - ) - - $stubVM2 = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() - $stubVM2.Name = 'DuplicateVM' - $stubVM2.HardDrives = @( - $stubVhdxDisk, - $stubVhdDisk - ) - $stubVM2.Path = $StubVMConfig.FullPath - $stubVM2.Generation = 1 - $stubVM2.MemoryStartup = 512MB - $stubVM2.MemoryMinimum = 128MB - $stubVM2.MemoryMaximum = 4096MB - $stubVM2.ProcessorCount = 1 - $stubVM2.ID = $mockVmGuid - $stubVM2.CPUUsage = 10 - $stubVM2.MemoryAssigned = 512MB - $stubVM2.Uptime = New-TimeSpan -Hours 12 - $stubVM2.CreationTime = (Get-Date).AddHours(-12) - $stubVM2.DynamicMemoryEnabled = $true - $stubVM2.Notes = '' - $stubVM2.State = 'Off' - $stubVM2.NetworkAdapters = @( - $stubNIC1, - $stubNIC2 - ) - - return @( - $stubVM1, - $stubVM2 - ) - } - - Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'Generation1Vhd' } -MockWith { - $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() - $stubVM.Name = 'Generation1Vhd' - $stubVM.HardDrives = @( - $stubVhdDisk - ) - $stubVM.Path = $StubVMConfig.FullPath - $stubVM.Generation = 1 - $stubVM.MemoryStartup = 512MB - $stubVM.MemoryMinimum = 128MB - $stubVM.MemoryMaximum = 4096MB - $stubVM.ProcessorCount = 1 - $stubVM.ID = $mockVmGuid - $stubVM.CPUUsage = 10 - $stubVM.MemoryAssigned = 512MB - $stubVM.Uptime = New-TimeSpan -Hours 12 - $stubVM.CreationTime = (Get-Date).AddHours(-12) - $stubVM.DynamicMemoryEnabled = $true - $stubVM.Notes = '' - $stubVM.State = 'Running' - $stubVM.NetworkAdapters = @( - $stubNIC1, - $stubNIC2 - ) - - return $stubVM - } - - Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'Generation2VM' } -MockWith { - $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() - $stubVM.Name = 'Generation2VM' - $stubVM.HardDrives = @( - $stubVhdxDisk - ) - $stubVM.Path = $StubVMConfig.FullPath - $stubVM.Generation = 2 - $stubVM.MemoryStartup = 512MB - $stubVM.MemoryMinimum = 128MB - $stubVM.MemoryMaximum = 4096MB - $stubVM.ProcessorCount = 1 - $stubVM.ID = $mockVmGuid - $stubVM.CPUUsage = 10 - $stubVM.MemoryAssigned = 512MB - $stubVM.Uptime = New-TimeSpan -Hours 12 - $stubVM.CreationTime = (Get-Date).AddHours(-12) - $stubVM.DynamicMemoryEnabled = $true - $stubVM.Notes = '' - $stubVM.State = 'Running' - $stubVM.NetworkAdapters = @( - $stubNIC1, - $stubNIC2 - ) - - return $stubVM - } - - Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'VMWithAutomaticCheckpoints' } -MockWith { - $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() - $stubVM.Name = 'VMWithAutomaticCheckpoints' - $stubVM.HardDrives = @( - $stubVhdxDisk - ) - $stubVM.Path = $StubVMConfig.FullPath - $stubVM.Generation = 2 - $stubVM.MemoryStartup = 512MB - $stubVM.MemoryMinimum = 128MB - $stubVM.MemoryMaximum = 4096MB - $stubVM.ProcessorCount = 1 - $stubVM.ID = $mockVmGuid - $stubVM.CPUUsage = 10 - $stubVM.MemoryAssigned = 512MB - $stubVM.Uptime = New-TimeSpan -Hours 12 - $stubVM.CreationTime = (Get-Date).AddHours(-12) - $stubVM.DynamicMemoryEnabled = $true - $stubVM.Notes = '' - $stubVM.State = 'Running' - $stubVM.AutomaticCheckpointsEnabled = $true - $stubVM.NetworkAdapters = @( - $stubNIC1, - $stubNIC2 - ) - - return $stubVM - } - - Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'VMWithoutAutomaticCheckpoints' } -MockWith { - $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() - $stubVM.Name = 'VMWithoutAutomaticCheckpoints' - $stubVM.HardDrives = @( - $stubVhdxDisk - ) - $stubVM.Path = $StubVMConfig.FullPath - $stubVM.Generation = 2 - $stubVM.MemoryStartup = 512MB - $stubVM.MemoryMinimum = 128MB - $stubVM.MemoryMaximum = 4096MB - $stubVM.ProcessorCount = 1 - $stubVM.ID = $mockVmGuid - $stubVM.CPUUsage = 10 - $stubVM.MemoryAssigned = 512MB - $stubVM.Uptime = New-TimeSpan -Hours 12 - $stubVM.CreationTime = (Get-Date).AddHours(-12) - $stubVM.DynamicMemoryEnabled = $true - $stubVM.Notes = '' - $stubVM.State = 'Running' - $stubVM.AutomaticCheckpointsEnabled = $false - $stubVM.NetworkAdapters = @( - $stubNIC1, - $stubNIC2 - ) - - return $stubVM - } - - Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'VMAutomaticCheckpointsUnsupported' } -MockWith { - $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() - $stubVM.Name = 'VMAutomaticCheckpointsUnsupported' - $stubVM.HardDrives = @( - $stubVhdxDisk - ) - $stubVM.Path = $StubVMConfig.FullPath - $stubVM.Generation = 2 - $stubVM.MemoryStartup = 512MB - $stubVM.MemoryMinimum = 128MB - $stubVM.MemoryMaximum = 4096MB - $stubVM.ProcessorCount = 1 - $stubVM.ID = $mockVmGuid - $stubVM.CPUUsage = 10 - $stubVM.MemoryAssigned = 512MB - $stubVM.Uptime = New-TimeSpan -Hours 12 - $stubVM.CreationTime = (Get-Date).AddHours(-12) - $stubVM.DynamicMemoryEnabled = $true - $stubVM.Notes = '' - $stubVM.State = 'Running' - $stubVM.NetworkAdapters = @( - $stubNIC1, - $stubNIC2 - ) - - return $stubVM - } - - $stubGuestServiceInterfaceId = 'Microsoft:{0}\6C09BB55-D683-4DA0-8931-C9BF705F6480' -f $mockVmGuid - - Mock -CommandName Get-VMIntegrationService -MockWith { - $guestServiceInterface = [Microsoft.HyperV.PowerShell.VMIntegrationComponent]::CreateTypeInstance() - $guestServiceInterface.Enabled = $false - $guestServiceInterface.Id = $stubGuestServiceInterfaceId - - return $guestServiceInterface - } - - Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } -MockWith { return $true } - Mock -CommandName Get-VhdHierarchy -ParameterFilter { $VhdPath.EndsWith('.vhd') } -MockWith { - # Return single Vhd chain for .vhds - return @($stubVhdDisk.Path) - } - Mock -CommandName Get-VhdHierarchy -ParameterFilter { $VhdPath.EndsWith('.vhdx') } -MockWith { - # Return snapshot hierarchy for .vhdxs - return @($stubVhdxDiskSnapshot.FullName, $stubVhdxDisk.Path) - } - Context 'Validates Get-TargetResource Method' { - - It 'Returns a hashtable' { - $targetResource = Get-TargetResource -Name 'RunningVM' -VhdPath $stubVhdxDisk.Path - $targetResource -is [System.Collections.Hashtable] | Should -Be $true - } - - It 'throws when multiple VMs are present' { - { Get-TargetResource -Name 'DuplicateVM' -VhdPath $stubVhdxDisk.Path } | Should -Throw - } - - It 'Does not call Get-VMFirmware if a generation 1 VM' { - Mock -CommandName Get-VMFirmware -MockWith { throw } - $null = Get-TargetResource -Name 'RunningVM' -VhdPath $stubVhdxDisk.Path - Assert-MockCalled -CommandName Get-VMFirmware -Scope It -Exactly 0 - } - - It 'Calls Get-VMFirmware if a generation 2 VM' { - Mock -CommandName Get-VMFirmware -MockWith { return $true } - $null = Get-TargetResource -Name 'Generation2VM' -VhdPath $stubVhdxDisk.Path - Assert-MockCalled -CommandName Get-VMFirmware -Scope It -Exactly 1 - } - - It 'Hash table contains key EnableGuestService' { - $targetResource = Get-TargetResource -Name 'RunningVM' -VhdPath $stubVhdxDisk.Path - $targetResource.ContainsKey('EnableGuestService') | Should -Be $true - } - It 'Hash table contains key AutomaticCheckpointEnabled' { - $targetResource = Get-TargetResource -Name 'VMWithAutomaticCheckpoints' -VhdPath $stubVhdxDisk.Path - $targetResource.ContainsKey('AutomaticCheckpointsEnabled') | Should -Be $true - } - It 'throws when Hyper-V Tools are not installed' { - # This test needs to be the last in the Context otherwise all subsequent Get-Module checks will fail - Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } - { Get-TargetResource -Name 'RunningVM' @testParams } | Should -Throw - } - } #end context Validates Get-TargetResource Method - - Context 'Validates Test-TargetResource Method' { - $testParams = @{ - VhdPath = $stubVhdxDisk.Path - } - - It 'Returns a boolean' { - $targetResource = Test-TargetResource -Name 'RunningVM' @testParams - $targetResource -is [System.Boolean] | Should -Be $true - } - - It 'Returns $true when VM is present and "Ensure" = "Present"' { - Test-TargetResource -Name 'RunningVM' @testParams | Should -Be $true - } - - It 'Returns $false when VM is not present and "Ensure" = "Present"' { - Test-TargetResource -Name 'NonexistentVM' @testParams | Should -Be $false - } - - It 'Returns $true when VM is not present and "Ensure" = "Absent"' { - Test-TargetResource -Name 'NonexistentVM' -Ensure Absent @testParams | Should -Be $true - } - - It 'Returns $false when VM is present and "Ensure" = "Absent"' { - Test-TargetResource -Name 'RunningVM' -Ensure Absent @testParams | Should -Be $false - } - - It 'Returns $true when VM is in the "Running" state and no state is explicitly specified' { - Test-TargetResource -Name 'RunningVM' @testParams | Should -Be $true - } - - It 'Returns $true when VM is in the "Stopped" state and no state is explicitly specified' { - Test-TargetResource -Name 'StoppedVM' @testParams | Should -Be $true - } - - It 'Returns $true when VM is in the "Paused" state and no state is explicitly specified' { - Test-TargetResource -Name 'PausedVM' @testParams | Should -Be $true - } - - It 'Returns $true when VM is in the "Running" state and requested "State" = "Running"' { - Test-TargetResource -Name 'RunningVM' @testParams | Should -Be $true - } - - It 'Returns $true when VM is in the "Off" state and requested "State" = "Off"' { - Test-TargetResource -Name 'StoppedVM' -State Off @testParams | Should -Be $true - } - - It 'Returns $true when VM is in the "Paused" state and requested "State" = Paused"' { - Test-TargetResource -Name 'PausedVM' -State Paused @testParams | Should -Be $true - } - - It 'Returns $false when VM is in the "Running" state and requested "State" = "Off"' { - Test-TargetResource -Name 'RunningVM' -State Off @testParams | Should -Be $false - } - - It 'Returns $false when VM is in the "Off" state and requested "State" = "Runnning"' { - Test-TargetResource -Name 'StoppedVM' -State Running @testParams | Should -Be $false - } - - It 'Returns $true when VM .vhd file is specified with a generation 1 VM' { - Test-TargetResource -Name 'Generation1Vhd' -VhdPath $stubVhdDisk.Path -Generation 1 -Verbose | Should -Be $true - } - - It 'Returns $true when VM .vhdx file is specified with a generation 1 VM' { - Test-TargetResource -Name 'StoppedVM' -VhdPath $stubVhdxDisk.Path -Generation 1 | Should -Be $true - } - - It 'Returns $true when VM .vhdx file is specified with a generation 2 VM' { - Mock -CommandName Test-VMSecureBoot -MockWith { return $true } - Test-TargetResource -Name 'Generation2VM' -Generation 2 @testParams | Should -Be $true - } - - It 'throws when a VM .vhd file is specified with a generation 2 VM' { - { Test-TargetResource -Name 'Gen2VM' -VhdPath $stubVhdDisk.Path -Generation 2 } | Should -Throw - } - - It 'Returns $true when multiple NICs are assigned in the correct order' { - Test-TargetResource -Name 'RunningVM' @testParams -SwitchName @($stubNIC1.SwitchName, $stubNIC2.SwitchName) | Should -Be $true - } - - It 'Returns $false when multiple NICs are not assigned/assigned in the wrong order' { - Test-TargetResource -Name 'RunningVM' @testParams -SwitchName @($stubNIC2.SwitchName, $stubNIC1.SwitchName) | Should -Be $false - } - - It 'Returns $true when multiple MAC addresses are assigned in the correct order' { - Test-TargetResource -Name 'RunningVM' @testParams -MACAddress @($stubNIC1.MACAddress, $stubNIC2.MACAddress) | Should -Be $true - } - - It 'Returns $false when multiple MAC addresses not assigned/assigned in the wrong order' { - Test-TargetResource -Name 'RunningVM' @testParams -MACAddress @($stubNIC1.MACAddress, $stubNIC2.MACAddress) | Should -Be $true - } - - It 'Returns $true regardless of "SecureBoot" setting on a generation 1 VM' { - Test-TargetResource -Name 'RunningVM' -SecureBoot $true @testParams | Should -Be $true - Test-TargetResource -Name 'RunningVM' -SecureBoot $false @testParams | Should -Be $true - } - - It 'Returns $true when SecureBoot is On and requested "SecureBoot" = "$true"' { - Mock -CommandName Test-VMSecureBoot -MockWith { return $true } - Test-TargetResource -Name 'Generation2VM' -Generation 2 @testParams | Should -Be $true - } - - It 'Returns $false when SecureBoot is On and requested "SecureBoot" = "$false"' { - Mock -CommandName Test-VMSecureBoot -MockWith { return $true } - Test-TargetResource -Name 'Generation2VM' -SecureBoot $false -Generation 2 @testParams | Should -Be $false - } - - It 'Returns $true when VM has snapshot chain' { - Mock -CommandName Get-VhdHierarchy -MockWith { - return @($studVhdxDiskSnapshot, $stubVhdxDisk) - } - Test-TargetResource -Name 'Generation2VM' -VhdPath $stubVhdxDisk.Path -Verbose | Should -Be $true - } - - It 'Returns $false when EnableGuestService is off and requested "EnableGuestService" = "$true"' { - Test-TargetResource -Name 'RunningVM' -EnableGuestService $true @testParams | Should -Be $false - } - - It 'Returns $true when EnableGuestService is off and "EnableGuestService" is not requested"' { - Test-TargetResource -Name 'RunningVM' @testParams | Should -Be $true - } - - Mock -CommandName Get-Command -ParameterFilter { $Name -eq 'Set-VM' -and $Module -eq 'Hyper-V' } -MockWith { - [pscustomobject]@{ - parameters = @{ - # Does not contains parameter AutomaticCheckpointsEnabled - } - } - } - It 'throws when AutomaticCheckpointsEnabled is configured but not supported' { - { Test-TargetResource -Name 'VMAutomaticCheckpoinstUnsupported' -AutomaticCheckpointsEnabled $true @testParams } | Should -Throw - } - - Mock -CommandName Get-Command -ParameterFilter { $Name -eq 'Set-VM' -and $Module -eq 'Hyper-V' } -MockWith { - [pscustomobject]@{ - parameters = @{ - 'AutomaticCheckpointsEnabled' = '' - } - } - } - It 'Returns $true when AutomaticCheckpointsEnabled is on and requested "AutomaticCheckpointsEnabled" is not requested' { - Test-TargetResource -Name 'VMWithAutomaticCheckpoints' @testParams | Should -Be $true - } - It 'Returns $true when AutomaticCheckpointsEnabled is on and requested "AutomaticCheckpointsEnabled" = "$true"' { - Test-TargetResource -Name 'VMWithAutomaticCheckpoints' -AutomaticCheckpointsEnabled $true @testParams | Should -Be $true - } - It 'Returns $true when AutomaticCheckpointsEnabled is off and requested "AutomaticCheckpointsEnabled" = "$false"' { - Test-TargetResource -Name 'VMWithoutAutomaticCheckpoints' -AutomaticCheckpointsEnabled $false @testParams | Should -Be $true - } - It 'Returns $false when AutomaticCheckpointsEnabled is off and requested "AutomaticCheckpointsEnabled" = "$true"' { - Test-TargetResource -Name 'VMWithoutAutomaticCheckpoints' -AutomaticCheckpointsEnabled $true @testParams | Should -Be $false - } - It 'Returns $false when AutomaticCheckpointsEnabled is on and requested "AutomaticCheckpointsEnabled" = "$false"' { - Test-TargetResource -Name 'VMWithAutomaticCheckpoints' -AutomaticCheckpointsEnabled $false @testParams | Should -Be $false - } - - It 'Returns $true when EnableGuestService is on and requested "EnableGuestService" = "$true"' { - Mock -CommandName Get-VMIntegrationService -MockWith { - $guestServiceInterface = [Microsoft.HyperV.PowerShell.VMIntegrationComponent]::CreateTypeInstance() - $guestServiceInterface.Enabled = $true - $guestServiceInterface.Id = $stubGuestServiceInterfaceId - - return $guestServiceInterface - } - - Test-TargetResource -Name 'RunningVM' -EnableGuestService $true @testParams | Should -Be $true - } - - It 'throws when Hyper-V Tools are not installed' { - # This test needs to be the last in the Context otherwise all subsequent Get-Module checks will fail - Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } - { Test-TargetResource -Name 'RunningVM' @testParams } | Should -Throw - } - - } #end context Validates Test-TargetResource Method - - Context 'Validates Set-TargetResource Method' { - $testParams = @{ - VhdPath = $stubVhdxDisk.Path - } - - Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'NewVM' } - Mock -CommandName New-VM -MockWith { - $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() - $stubVM.Name = 'NewVM' - $stubVM.Path = $StubVMConfig.FullPath - $stubVM.Generation = $Generation - $stubVM.ID = $mockVmGuid - $stubVM.State = 'Off' - - return $stubVM - } - - Mock -CommandName Set-VM -MockWith { return $true } - Mock -CommandName Stop-VM -MockWith { return $true } # requires output to be able to pipe something into Remove-VM - Mock -CommandName Remove-VM -MockWith { return $true } - Mock -CommandName Set-VMNetworkAdapter -MockWith { return $true } - Mock -CommandName Get-VMNetworkAdapter -MockWith { return $stubVM.NetworkAdapters.IpAddresses } - Mock -CommandName Set-VMState -MockWith { return $true } - Mock -CommandName Set-VMMemory - - It 'Removes an existing VM when "Ensure" = "Absent"' { - Set-TargetResource -Name 'RunningVM' -Ensure Absent @testParams - Assert-MockCalled -CommandName Remove-VM -Scope It - } - - It 'Creates and starts a VM VM with disabled dynamic memory that does not exist when "Ensure" = "Present" and "State" = "Running"' { - Set-TargetResource -Name 'NewVM' -State Running @testParams - Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName Set-VMState -Exactly -Times 1 -Scope It - } - - It 'Creates but does not start a VM with disabled dynamic memory that does not exist when "Ensure" = "Present"' { - Set-TargetResource -Name 'NewVM' @testParams - Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It - } - - It 'Creates but does not start a VM with disabled dynamic memory when only StartupMemory is specified' { - Set-TargetResource -Name 'NewVM' @testParams -StartupMemory 4GB - Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It - } - - It 'Creates but does not start a VM with disabled dynamic memory when identical values for startup, minimum and maximum memory are specified' { - Set-TargetResource -Name 'NewVM' @testParams -StartupMemory 4GB -MinimumMemory 4GB -MaximumMemory 4GB - Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName Set-VMMemory -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It - } - - It 'Creates but does not start a VM with enabled dynamic memory because a MinimumMemory value is specified' { - Set-TargetResource -Name 'NewVM' @testParams -MinimumMemory 512MB - Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName Set-VMMemory -Exactly -Times 0 -Scope It - Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It - } - - It 'Creates but does not start a VM with enabled dynamic memory because a MaximumMemory value is specified' { - Set-TargetResource -Name 'NewVM' @testParams -MaximumMemory 16GB - Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName Set-VMMemory -Exactly -Times 0 -Scope It - Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It - } - - It 'Does not change VM state when VM "State" = "Running" and requested "State" = "Running"' { - Set-TargetResource -Name 'RunningVM' -State Running @testParams - Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It - } - - It 'Does not change VM state when VM "State" = "Off" and requested "State" = "Off"' { - Set-TargetResource -Name 'StoppedVM' -State Off @testParams - Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It - } - - It 'Changes VM state when existing VM "State" = "Off" and requested "State" = "Running"' { - Set-TargetResource -Name 'StoppedVM' -State Running @testParams - Assert-MockCalled -CommandName Set-VMState -Exactly -Times 1 -Scope It - } - - It 'Changes VM state when existing VM "State" = "Running" and requested "State" = "Off"' { - Set-TargetResource -Name 'RunningVM' -State Off @testParams - Assert-MockCalled -CommandName Set-VMState -Exactly -Times 1 -Scope It - } - - It 'Creates a generation 1 VM by default/when not explicitly specified' { - Set-TargetResource -Name 'NewVM' @testParams - Assert-MockCalled -CommandName New-VM -ParameterFilter { $Generation -eq 1 } -Scope It - } - - It 'Creates a generation 1 VM when explicitly specified' { - Set-TargetResource -Name 'NewVM' -Generation 1 @testParams - Assert-MockCalled -CommandName New-VM -ParameterFilter { $Generation -eq 1 } -Scope It - } - - It 'Creates a generation 2 VM when explicitly specified' { - Set-TargetResource -Name 'NewVM' -Generation 2 @testParams - Assert-MockCalled -CommandName New-VM -ParameterFilter { $Generation -eq 2 } -Scope It - } - - It 'Calls "Add-VMNetworkAdapter" for each NIC when creating a new VM' { - Mock -CommandName Add-VMNetworkAdapter - Set-TargetResource -Name 'NewVM' @testParams -SwitchName 'Switch1', 'Switch2' - # The first NIC is assigned during the VM creation - Assert-MockCalled -CommandName Add-VMNetworkAdapter -Exactly 1 -Scope It - } - - It 'Calls "Connect-VMNetworkAdapter" for each existing NIC when updating an existing VM' { - Mock -CommandName Connect-VMNetworkAdapter - Set-TargetResource -Name 'StoppedVM' @testParams -SwitchName 'Switch1', 'Switch2' - # The first NIC is assigned during the VM creation - Assert-MockCalled -CommandName Connect-VMNetworkAdapter -Exactly 2 -Scope It - } - - It 'Calls "Add-VMNetworkAdapter" for each missing NIC when updating an existing VM' { - Mock -CommandName Connect-VMNetworkAdapter - Mock -CommandName Add-VMNetworkAdapter - Set-TargetResource -Name 'StoppedVM' @testParams -SwitchName 'Switch1', 'Switch2', 'Switch3' - # The first NIC is assigned during the VM creation - Assert-MockCalled -CommandName Connect-VMNetworkAdapter -Exactly 2 -Scope It - Assert-MockCalled -CommandName Add-VMNetworkAdapter -Exactly 1 -Scope It - } - - It 'Does not change switch assignments if no switch assignments are specified' { - Mock -CommandName Connect-VMNetworkAdapter - Set-TargetResource -Name 'StoppedVM' @testParams - Assert-MockCalled -CommandName Connect-VMNetworkAdapter -Exactly 0 -Scope It - } - - It 'Does not change NIC assignments if the switch assisgnments are correct' { - Mock -CommandName Set-VMNetworkAdapter - Set-TargetResource -Name 'StoppedVM' @testParams -SwitchName $stubNIC1.SwitchName, $stubNIC2.SwitchName - Assert-MockCalled -CommandName Set-VMNetworkAdapter -Exactly 0 -Scope It - } - - It 'Errors when updating MAC addresses on a running VM and "RestartIfNeeded" = "$false"' { - { Set-TargetResource -Name 'RunningVM' @testParams -MACAddress 'AABBCCDDEEFE', 'AABBCCDDEEFF' -ErrorAction Stop } | Should -Throw - } - - It 'Does not change MAC addresses if no MAC addresses assignments are specified' { - Mock -CommandName Set-VMNetworkAdapter -ParameterFilter { $StaticMacAddress -ne $null } - Set-TargetResource -Name 'StoppedVM' @testParams - Assert-MockCalled -CommandName Set-VMNetworkAdapter -ParameterFilter { $StaticMacAddress -ne $null } -Exactly 0 -Scope It - } - - It 'Calls "Set-VMNetworkAdapter" for each MAC address on a stopped VM' { - Mock -CommandName Set-VMNetworkAdapter - Set-TargetResource -Name 'StoppedVM' @testParams -MACAddress 'AABBCCDDEEFE', 'AABBCCDDEEFF' - # The first NIC is assigned during the VM creation - Assert-MockCalled -CommandName Set-VMNetworkAdapter -Exactly 2 -Scope It - } - - It 'Does not change Secure Boot call "Set-VMProperty" when creating a generation 1 VM' { - Mock -CommandName Set-VMProperty - Set-TargetResource -Name 'RunningVM' @testParams - Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 0 -Scope It - } - - It 'Does call "Set-VMProperty" when creating a generation 2 VM' { - Mock -CommandName Test-VMSecureBoot -MockWith { return $true } - Mock -CommandName Set-VMProperty - Set-TargetResource -Name 'RunningVM' -Generation 2 -SecureBoot $false @testParams - Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 1 -Scope It - } - - It 'Does not change Secure Boot for generation 1 VM' { - Mock -CommandName Test-VMSecureBoot -MockWith { return $true } - Mock -CommandName Set-VMProperty - Set-TargetResource -Name 'StoppedVM' -SecureBoot $true @testParams - Set-TargetResource -Name 'StoppedVM' -SecureBoot $false @testParams - Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 0 -Scope It - } - - It 'Does not change Secure Boot for generation 2 VM with VM "SecureBoot" match' { - Mock -CommandName Test-VMSecureBoot -MockWith { return $true } - Mock -CommandName Set-VMProperty - Set-TargetResource -Name 'StoppedVM' -SecureBoot $true -Generation 2 @testParams - Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 0 -Scope It - } - - It 'Does change Secure Boot for generation 2 VM with VM "SecureBoot" mismatch' { - Mock -CommandName Test-VMSecureBoot -MockWith { return $false } - Mock -CommandName Set-VMProperty - Set-TargetResource -Name 'StoppedVM' -SecureBoot $true -Generation 2 @testParams - Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 1 -Scope It - } - - It 'Does call "Enable-VMIntegrationService" when "EnableGuestService" = "$true"' { - Mock -CommandName Enable-VMIntegrationService - Set-TargetResource -Name 'RunningVM' -EnableGuestService $true @testParams - Assert-MockCalled -CommandName Enable-VMIntegrationService -Exactly -Times 1 -Scope It - } - - It 'Does call "Disable-VMIntegrationService" when "Guest Service Interface" = "Enabled" and "EnableGuestService" = "$false" specified' { - Mock -CommandName Disable-VMIntegrationService - Mock -CommandName Get-VMIntegrationService -MockWith { - $guestServiceInterface = [Microsoft.HyperV.PowerShell.VMIntegrationComponent]::CreateTypeInstance() - $guestServiceInterface.Enabled = $true - $guestServiceInterface.Id = $stubGuestServiceInterfaceId - - return $guestServiceInterface - } - - Set-TargetResource -Name 'RunningVM' -EnableGuestService $false @testParams - Assert-MockCalled -CommandName Disable-VMIntegrationService -Exactly -Times 1 -Scope It - } - - Mock -CommandName Get-Command -ParameterFilter { $Name -eq 'Set-VM' -and $Module -eq 'Hyper-V' } -MockWith { - [pscustomobject]@{ - parameters = @{ - # Does not contain parameter AutomaticCheckpointsEnabled - } - } - } - It 'throws when AutomaticCheckpointsEnabled is configured but not supported' { - { Set-TargetResource -Name 'VMAutomaticCheckpointsUnsupported' -AutomaticCheckpointsEnabled $true @testParams } | Should -Throw - } - It 'Does not call "Set-VM" when "AutomaticCheckpointsEnabled" is unsupported and unspecified' { - Set-TargetResource -Name 'VMAutomaticCheckpointsUnsupported' @testParams - Assert-MockCalled -CommandName Set-VM -Exactly -Times 0 -Scope It - } - - Mock -CommandName Get-Command -ParameterFilter { $Name -eq 'Set-VM' -and $Module -eq 'Hyper-V' } -MockWith { - [pscustomobject]@{ - parameters = @{ - 'AutomaticCheckpointsEnabled' = '' - } - } - } - $AutomaticCheckpointsEnabledTestCases = @( - @{ - VMName = 'VMWithAutomaticCheckpoints' - SetAutomaticCheckpointsEnabled = $true - Assert = 'Does not call "Set-VM"' - Times = 0 - }, - @{ - VMName = 'VMWithoutAutomaticCheckpoints' - SetAutomaticCheckpointsEnabled = $false - Assert = 'Does not call "Set-VM"' - Times = 0 - }, - @{ - VMName = 'VMWithAutomaticCheckpoints' - SetAutomaticCheckpointsEnabled = $false - Assert = 'Does call "Set-VM"' - Times = 1 - }, - @{ - VMName = 'VMWithoutAutomaticCheckpoints' - SetAutomaticCheckpointsEnabled = $true - Assert = 'Does call "Set-VM"' - Times = 1 - } - ) - It ' on VM when "AutomaticCheckpointsEnabled" is set to ""' -TestCases $AutomaticCheckpointsEnabledTestCases { - param - ( - $VMName, - $SetAutomaticCheckpointsEnabled, - $Times - ) - - Set-TargetResource -Name $VMName -AutomaticCheckpointsEnabled $SetAutomaticCheckpointsEnabled @testParams - Assert-MockCalled -CommandName Set-VM -ParameterFilter { $Name -eq $VMName -and $AutomaticCheckpointsEnabled -eq $SetAutomaticCheckpointsEnabled } -Exactly -Times $Times -Scope It - } - It 'Disables dynamic memory of RuningVM if only StartupMemory specified' { - Mock -CommandName Set-VMProperty - Set-TargetResource -Name 'RunningVM' -StartupMemory 4GB @testParams - Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { - $VMCommand -eq 'Set-VM' -and - ($ChangeProperty.StaticMemory -eq $true) -and - ($ChangeProperty.DynamicMemory -eq $false) - } -Exactly -Times 1 -Scope It - } - - It 'Disables dynamic memory of RunningVM if StartupMemory, MinimumMemory and MaximumMemory are specified with the same values' { - Mock -CommandName Set-VMProperty - Set-TargetResource -Name 'RunningVM' -StartupMemory 4GB -MinimumMemory 4GB -MaximumMemory 4GB @testParams - Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { - $VMCommand -eq 'Set-VM' -and - ($ChangeProperty.StaticMemory -eq $true) -and - ($ChangeProperty.DynamicMemory -eq $false) - } -Exactly -Times 1 -Scope It - } - - It 'Enables dynamic memory of RuningVM if MinimumMemory is specified ' { - Mock -CommandName Set-VMProperty - Set-TargetResource -Name 'RunningVM' -MinimumMemory 4GB @testParams - Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { - $VMCommand -eq 'Set-VM' -and - ($ChangeProperty.StaticMemory -eq $false) -and - ($ChangeProperty.DynamicMemory -eq $true) - } -Exactly -Times 1 -Scope It - } - - It 'Enables dynamic memory of RuningVM if MaximumMemory is specified ' { - Mock -CommandName Set-VMProperty - Set-TargetResource -Name 'RunningVM' -MaximumMemory 4GB @testParams - Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { - $VMCommand -eq 'Set-VM' -and - ($ChangeProperty.StaticMemory -eq $false) -and - ($ChangeProperty.DynamicMemory -eq $true) - } -Exactly -Times 1 -Scope It - } - - It 'throws when Hyper-V Tools are not installed' { - Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } - { Set-TargetResource -Name 'RunningVM' @testParams } | Should -Throw - } - } #end context Validates Set-TargetResource Method - - Context 'Validates Test-VMSecureBoot Method' { - BeforeAll { - Mock -CommandName Get-VM -MockWith { - $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() - $stubVM.Name = 'NewVM' - $stubVM.Path = $StubVMConfig.FullPath - $stubVM.Generation = $Generation - $stubVM.ID = $mockVmGuid - $stubVM.State = 'Off' - - return $stubVM - } - } - - It 'Returns $true when "SecureBoot" = "On"' { - Mock -CommandName Get-VMFirmware -MockWith { - return [PSCustomObject] @{ - SecureBoot = 'On' - } - } - - Test-VMSecureBoot -Name 'TestVM' | Should -Be $true - } - - It 'Returns $false when "SecureBoot" = "Off"' { - Mock -CommandName Get-VMFirmware -MockWith { - return [PSCustomObject] @{ - SecureBoot = 'Off' - } - } - - Test-VMSecureBoot -Name 'TestVM' | Should -Be $false - } - - } #end context Validates Test-VMSecureBoot Method - - Context 'Validates Get-VhdHierarchy Method' { - It 'Does not throw with null parent path (#52)' { - # Must use a different file extension to ensure existing mocks Get-VhdHierarchy or not called - $fakeVhdPath = 'BaseVhd.avhdx' - - Mock -CommandName Get-VHD -ParameterFilter { $Path -eq $fakeVhdPath } -MockWith { - return [PSCustomObject] @{ - Path = $fakeVhdPath - ParentPath = $null - } - } - - { Get-VhdHierarchy -VhdPath $fakeVhdPath } | Should -Not -throw - } - - } #end context validates Get-VhdHierarchy - } #end describe xVMHyper-V - } #end inmodulescope -} -finally -{ - Invoke-TestCleanup -} +# $script:dscModuleName = 'HyperVDsc' +# $script:dscResourceName = 'DSC_VMHyperV' + +# function Invoke-TestSetup +# { +# try +# { +# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' +# } +# catch [System.IO.FileNotFoundException] +# { +# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' +# } + +# $script:testEnvironment = Initialize-TestEnvironment ` +# -DSCModuleName $script:dscModuleName ` +# -DSCResourceName $script:dscResourceName ` +# -ResourceType 'Mof' ` +# -TestType 'Unit' + +# # Import the stub functions. +# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +# } + +# function Invoke-TestCleanup +# { +# Restore-TestEnvironment -TestEnvironment $script:testEnvironment +# } + +# Invoke-TestSetup + +# try +# { +# InModuleScope $script:dscResourceName { +# Describe 'xVMHyper-V' { +# $null = New-Item -Path 'TestDrive:\TestVM.vhdx' -ItemType File +# $null = New-Item -Path 'TestDrive:\TestVM.vhd' -ItemType File + +# $stubVhdxDisk = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() +# $stubVhdxDisk.Path = 'TestDrive:\TestVM.vhdx' + +# $stubVhdDisk = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() +# $stubVhdDisk.Path = 'TestDrive:\TestVM.vhd' + +# $studVhdxDiskSnapshot = New-Item -Path "TestDrive:\TestVM_D0145678-1576-4435-AB18-9F000C1C17D0.avhdx" -ItemType File +# $StubVMConfig = New-Item -Path 'TestDrive:\TestVM.xml' -ItemType File + +# # Mock the class VMNetworkAdapter to support piping to cmdlet Connect-VMNetworkAdapter +# $stubNIC1 = [Microsoft.HyperV.PowerShell.VMNetworkAdapter]::CreateTypeInstance() +# $stubNIC1.SwitchName = 'Test Switch 1' +# $stubNIC1.MacAddress = 'AA-BB-CC-DD-EE-FF' +# $stubNIC1.IpAddresses = @('192.168.0.1', '10.0.0.1') + +# # Mock the class VMNetworkAdapter to support piping to cmdlet Connect-VMNetworkAdapter +# $stubNIC2 = [Microsoft.HyperV.PowerShell.VMNetworkAdapter]::CreateTypeInstance() +# $stubNIC2.SwitchName = 'Test Switch 2' +# $stubNIC2.MacAddress = 'AA-BB-CC-DD-EE-FE' +# $stubNIC2.IpAddresses = @('192.168.1.1') + +# $mockVmGuid = [System.Guid]::NewGuid().ToString() + +# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'RunningVM' } -MockWith { +# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() +# $stubVM.Name = 'RunningVM' +# $stubVM.HardDrives = @( +# $stubVhdxDisk, +# $stubVhdDisk +# ) +# $stubVM.Path = $StubVMConfig.FullPath +# $stubVM.Generation = 1 +# $stubVM.MemoryStartup = 512MB +# $stubVM.MemoryMinimum = 128MB +# $stubVM.MemoryMaximum = 4096MB +# $stubVM.ProcessorCount = 1 +# $stubVM.ID = $mockVmGuid +# $stubVM.CPUUsage = 10 +# $stubVM.MemoryAssigned = 512MB +# $stubVM.Uptime = New-TimeSpan -Hours 12 +# $stubVM.CreationTime = (Get-Date).AddHours(-12) +# $stubVM.DynamicMemoryEnabled = $true +# $stubVM.Notes = '' +# $stubVM.State = 'Running' +# $stubVM.NetworkAdapters = @( +# $stubNIC1, +# $stubNIC2 +# ) + +# return $stubVM +# } + +# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'StoppedVM' } -MockWith { +# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() +# $stubVM.Name = 'StoppedVM' +# $stubVM.HardDrives = @( +# $stubVhdxDisk, +# $stubVhdDisk +# ) +# $stubVM.Path = $StubVMConfig.FullPath +# $stubVM.Generation = 1 +# $stubVM.MemoryStartup = 512MB +# $stubVM.MemoryMinimum = 128MB +# $stubVM.MemoryMaximum = 4096MB +# $stubVM.ProcessorCount = 1 +# $stubVM.ID = $mockVmGuid +# $stubVM.CPUUsage = 10 +# $stubVM.MemoryAssigned = 512MB +# $stubVM.Uptime = New-TimeSpan -Hours 12 +# $stubVM.CreationTime = (Get-Date).AddHours(-12) +# $stubVM.DynamicMemoryEnabled = $true +# $stubVM.Notes = '' +# $stubVM.State = 'Off' +# $stubVM.NetworkAdapters = @( +# $stubNIC1, +# $stubNIC2 +# ) + +# return $stubVM +# } + +# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'PausedVM' } -MockWith { +# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() +# $stubVM.Name = 'PausedVM' +# $stubVM.HardDrives = @( +# $stubVhdxDisk, +# $stubVhdDisk +# ) +# $stubVM.Path = $StubVMConfig.FullPath +# $stubVM.Generation = 1 +# $stubVM.MemoryStartup = 512MB +# $stubVM.MemoryMinimum = 128MB +# $stubVM.MemoryMaximum = 4096MB +# $stubVM.ProcessorCount = 1 +# $stubVM.ID = $mockVmGuid +# $stubVM.CPUUsage = 10 +# $stubVM.MemoryAssigned = 512MB +# $stubVM.Uptime = New-TimeSpan -Hours 12 +# $stubVM.CreationTime = (Get-Date).AddHours(-12) +# $stubVM.DynamicMemoryEnabled = $true +# $stubVM.Notes = '' +# $stubVM.State = 'Paused' +# $stubVM.NetworkAdapters = @( +# $stubNIC1, +# $stubNIC2 +# ) + +# return $stubVM +# } + +# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'NonexistentVM' } -MockWith { +# Write-Error 'VM not found.' +# } + +# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'DuplicateVM' } -MockWith { +# $stubVM1 = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() +# $stubVM1.Name = 'DuplicateVM' +# $stubVM1.HardDrives = @( +# $stubVhdxDisk, +# $stubVhdDisk +# ) +# $stubVM1.Path = $StubVMConfig.FullPath +# $stubVM1.Generation = 1 +# $stubVM1.MemoryStartup = 512MB +# $stubVM1.MemoryMinimum = 128MB +# $stubVM1.MemoryMaximum = 4096MB +# $stubVM1.ProcessorCount = 1 +# $stubVM1.ID = $mockVmGuid +# $stubVM1.CPUUsage = 10 +# $stubVM1.MemoryAssigned = 512MB +# $stubVM1.Uptime = New-TimeSpan -Hours 12 +# $stubVM1.CreationTime = (Get-Date).AddHours(-12) +# $stubVM1.DynamicMemoryEnabled = $true +# $stubVM1.Notes = '' +# $stubVM1.State = 'Off' +# $stubVM1.NetworkAdapters = @( +# $stubNIC1, +# $stubNIC2 +# ) + +# $stubVM2 = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() +# $stubVM2.Name = 'DuplicateVM' +# $stubVM2.HardDrives = @( +# $stubVhdxDisk, +# $stubVhdDisk +# ) +# $stubVM2.Path = $StubVMConfig.FullPath +# $stubVM2.Generation = 1 +# $stubVM2.MemoryStartup = 512MB +# $stubVM2.MemoryMinimum = 128MB +# $stubVM2.MemoryMaximum = 4096MB +# $stubVM2.ProcessorCount = 1 +# $stubVM2.ID = $mockVmGuid +# $stubVM2.CPUUsage = 10 +# $stubVM2.MemoryAssigned = 512MB +# $stubVM2.Uptime = New-TimeSpan -Hours 12 +# $stubVM2.CreationTime = (Get-Date).AddHours(-12) +# $stubVM2.DynamicMemoryEnabled = $true +# $stubVM2.Notes = '' +# $stubVM2.State = 'Off' +# $stubVM2.NetworkAdapters = @( +# $stubNIC1, +# $stubNIC2 +# ) + +# return @( +# $stubVM1, +# $stubVM2 +# ) +# } + +# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'Generation1Vhd' } -MockWith { +# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() +# $stubVM.Name = 'Generation1Vhd' +# $stubVM.HardDrives = @( +# $stubVhdDisk +# ) +# $stubVM.Path = $StubVMConfig.FullPath +# $stubVM.Generation = 1 +# $stubVM.MemoryStartup = 512MB +# $stubVM.MemoryMinimum = 128MB +# $stubVM.MemoryMaximum = 4096MB +# $stubVM.ProcessorCount = 1 +# $stubVM.ID = $mockVmGuid +# $stubVM.CPUUsage = 10 +# $stubVM.MemoryAssigned = 512MB +# $stubVM.Uptime = New-TimeSpan -Hours 12 +# $stubVM.CreationTime = (Get-Date).AddHours(-12) +# $stubVM.DynamicMemoryEnabled = $true +# $stubVM.Notes = '' +# $stubVM.State = 'Running' +# $stubVM.NetworkAdapters = @( +# $stubNIC1, +# $stubNIC2 +# ) + +# return $stubVM +# } + +# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'Generation2VM' } -MockWith { +# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() +# $stubVM.Name = 'Generation2VM' +# $stubVM.HardDrives = @( +# $stubVhdxDisk +# ) +# $stubVM.Path = $StubVMConfig.FullPath +# $stubVM.Generation = 2 +# $stubVM.MemoryStartup = 512MB +# $stubVM.MemoryMinimum = 128MB +# $stubVM.MemoryMaximum = 4096MB +# $stubVM.ProcessorCount = 1 +# $stubVM.ID = $mockVmGuid +# $stubVM.CPUUsage = 10 +# $stubVM.MemoryAssigned = 512MB +# $stubVM.Uptime = New-TimeSpan -Hours 12 +# $stubVM.CreationTime = (Get-Date).AddHours(-12) +# $stubVM.DynamicMemoryEnabled = $true +# $stubVM.Notes = '' +# $stubVM.State = 'Running' +# $stubVM.NetworkAdapters = @( +# $stubNIC1, +# $stubNIC2 +# ) + +# return $stubVM +# } + +# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'VMWithAutomaticCheckpoints' } -MockWith { +# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() +# $stubVM.Name = 'VMWithAutomaticCheckpoints' +# $stubVM.HardDrives = @( +# $stubVhdxDisk +# ) +# $stubVM.Path = $StubVMConfig.FullPath +# $stubVM.Generation = 2 +# $stubVM.MemoryStartup = 512MB +# $stubVM.MemoryMinimum = 128MB +# $stubVM.MemoryMaximum = 4096MB +# $stubVM.ProcessorCount = 1 +# $stubVM.ID = $mockVmGuid +# $stubVM.CPUUsage = 10 +# $stubVM.MemoryAssigned = 512MB +# $stubVM.Uptime = New-TimeSpan -Hours 12 +# $stubVM.CreationTime = (Get-Date).AddHours(-12) +# $stubVM.DynamicMemoryEnabled = $true +# $stubVM.Notes = '' +# $stubVM.State = 'Running' +# $stubVM.AutomaticCheckpointsEnabled = $true +# $stubVM.NetworkAdapters = @( +# $stubNIC1, +# $stubNIC2 +# ) + +# return $stubVM +# } + +# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'VMWithoutAutomaticCheckpoints' } -MockWith { +# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() +# $stubVM.Name = 'VMWithoutAutomaticCheckpoints' +# $stubVM.HardDrives = @( +# $stubVhdxDisk +# ) +# $stubVM.Path = $StubVMConfig.FullPath +# $stubVM.Generation = 2 +# $stubVM.MemoryStartup = 512MB +# $stubVM.MemoryMinimum = 128MB +# $stubVM.MemoryMaximum = 4096MB +# $stubVM.ProcessorCount = 1 +# $stubVM.ID = $mockVmGuid +# $stubVM.CPUUsage = 10 +# $stubVM.MemoryAssigned = 512MB +# $stubVM.Uptime = New-TimeSpan -Hours 12 +# $stubVM.CreationTime = (Get-Date).AddHours(-12) +# $stubVM.DynamicMemoryEnabled = $true +# $stubVM.Notes = '' +# $stubVM.State = 'Running' +# $stubVM.AutomaticCheckpointsEnabled = $false +# $stubVM.NetworkAdapters = @( +# $stubNIC1, +# $stubNIC2 +# ) + +# return $stubVM +# } + +# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'VMAutomaticCheckpointsUnsupported' } -MockWith { +# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() +# $stubVM.Name = 'VMAutomaticCheckpointsUnsupported' +# $stubVM.HardDrives = @( +# $stubVhdxDisk +# ) +# $stubVM.Path = $StubVMConfig.FullPath +# $stubVM.Generation = 2 +# $stubVM.MemoryStartup = 512MB +# $stubVM.MemoryMinimum = 128MB +# $stubVM.MemoryMaximum = 4096MB +# $stubVM.ProcessorCount = 1 +# $stubVM.ID = $mockVmGuid +# $stubVM.CPUUsage = 10 +# $stubVM.MemoryAssigned = 512MB +# $stubVM.Uptime = New-TimeSpan -Hours 12 +# $stubVM.CreationTime = (Get-Date).AddHours(-12) +# $stubVM.DynamicMemoryEnabled = $true +# $stubVM.Notes = '' +# $stubVM.State = 'Running' +# $stubVM.NetworkAdapters = @( +# $stubNIC1, +# $stubNIC2 +# ) + +# return $stubVM +# } + +# $stubGuestServiceInterfaceId = 'Microsoft:{0}\6C09BB55-D683-4DA0-8931-C9BF705F6480' -f $mockVmGuid + +# Mock -CommandName Get-VMIntegrationService -MockWith { +# $guestServiceInterface = [Microsoft.HyperV.PowerShell.VMIntegrationComponent]::CreateTypeInstance() +# $guestServiceInterface.Enabled = $false +# $guestServiceInterface.Id = $stubGuestServiceInterfaceId + +# return $guestServiceInterface +# } + +# Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } -MockWith { return $true } +# Mock -CommandName Get-VhdHierarchy -ParameterFilter { $VhdPath.EndsWith('.vhd') } -MockWith { +# # Return single Vhd chain for .vhds +# return @($stubVhdDisk.Path) +# } +# Mock -CommandName Get-VhdHierarchy -ParameterFilter { $VhdPath.EndsWith('.vhdx') } -MockWith { +# # Return snapshot hierarchy for .vhdxs +# return @($stubVhdxDiskSnapshot.FullName, $stubVhdxDisk.Path) +# } +# Context 'Validates Get-TargetResource Method' { + +# It 'Returns a hashtable' { +# $targetResource = Get-TargetResource -Name 'RunningVM' -VhdPath $stubVhdxDisk.Path +# $targetResource -is [System.Collections.Hashtable] | Should -Be $true +# } + +# It 'throws when multiple VMs are present' { +# { Get-TargetResource -Name 'DuplicateVM' -VhdPath $stubVhdxDisk.Path } | Should -Throw +# } + +# It 'Does not call Get-VMFirmware if a generation 1 VM' { +# Mock -CommandName Get-VMFirmware -MockWith { throw } +# $null = Get-TargetResource -Name 'RunningVM' -VhdPath $stubVhdxDisk.Path +# Assert-MockCalled -CommandName Get-VMFirmware -Scope It -Exactly 0 +# } + +# It 'Calls Get-VMFirmware if a generation 2 VM' { +# Mock -CommandName Get-VMFirmware -MockWith { return $true } +# $null = Get-TargetResource -Name 'Generation2VM' -VhdPath $stubVhdxDisk.Path +# Assert-MockCalled -CommandName Get-VMFirmware -Scope It -Exactly 1 +# } + +# It 'Hash table contains key EnableGuestService' { +# $targetResource = Get-TargetResource -Name 'RunningVM' -VhdPath $stubVhdxDisk.Path +# $targetResource.ContainsKey('EnableGuestService') | Should -Be $true +# } +# It 'Hash table contains key AutomaticCheckpointEnabled' { +# $targetResource = Get-TargetResource -Name 'VMWithAutomaticCheckpoints' -VhdPath $stubVhdxDisk.Path +# $targetResource.ContainsKey('AutomaticCheckpointsEnabled') | Should -Be $true +# } +# It 'throws when Hyper-V Tools are not installed' { +# # This test needs to be the last in the Context otherwise all subsequent Get-Module checks will fail +# Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } +# { Get-TargetResource -Name 'RunningVM' @testParams } | Should -Throw +# } +# } #end context Validates Get-TargetResource Method + +# Context 'Validates Test-TargetResource Method' { +# $testParams = @{ +# VhdPath = $stubVhdxDisk.Path +# } + +# It 'Returns a boolean' { +# $targetResource = Test-TargetResource -Name 'RunningVM' @testParams +# $targetResource -is [System.Boolean] | Should -Be $true +# } + +# It 'Returns $true when VM is present and "Ensure" = "Present"' { +# Test-TargetResource -Name 'RunningVM' @testParams | Should -Be $true +# } + +# It 'Returns $false when VM is not present and "Ensure" = "Present"' { +# Test-TargetResource -Name 'NonexistentVM' @testParams | Should -Be $false +# } + +# It 'Returns $true when VM is not present and "Ensure" = "Absent"' { +# Test-TargetResource -Name 'NonexistentVM' -Ensure Absent @testParams | Should -Be $true +# } + +# It 'Returns $false when VM is present and "Ensure" = "Absent"' { +# Test-TargetResource -Name 'RunningVM' -Ensure Absent @testParams | Should -Be $false +# } + +# It 'Returns $true when VM is in the "Running" state and no state is explicitly specified' { +# Test-TargetResource -Name 'RunningVM' @testParams | Should -Be $true +# } + +# It 'Returns $true when VM is in the "Stopped" state and no state is explicitly specified' { +# Test-TargetResource -Name 'StoppedVM' @testParams | Should -Be $true +# } + +# It 'Returns $true when VM is in the "Paused" state and no state is explicitly specified' { +# Test-TargetResource -Name 'PausedVM' @testParams | Should -Be $true +# } + +# It 'Returns $true when VM is in the "Running" state and requested "State" = "Running"' { +# Test-TargetResource -Name 'RunningVM' @testParams | Should -Be $true +# } + +# It 'Returns $true when VM is in the "Off" state and requested "State" = "Off"' { +# Test-TargetResource -Name 'StoppedVM' -State Off @testParams | Should -Be $true +# } + +# It 'Returns $true when VM is in the "Paused" state and requested "State" = Paused"' { +# Test-TargetResource -Name 'PausedVM' -State Paused @testParams | Should -Be $true +# } + +# It 'Returns $false when VM is in the "Running" state and requested "State" = "Off"' { +# Test-TargetResource -Name 'RunningVM' -State Off @testParams | Should -Be $false +# } + +# It 'Returns $false when VM is in the "Off" state and requested "State" = "Runnning"' { +# Test-TargetResource -Name 'StoppedVM' -State Running @testParams | Should -Be $false +# } + +# It 'Returns $true when VM .vhd file is specified with a generation 1 VM' { +# Test-TargetResource -Name 'Generation1Vhd' -VhdPath $stubVhdDisk.Path -Generation 1 -Verbose | Should -Be $true +# } + +# It 'Returns $true when VM .vhdx file is specified with a generation 1 VM' { +# Test-TargetResource -Name 'StoppedVM' -VhdPath $stubVhdxDisk.Path -Generation 1 | Should -Be $true +# } + +# It 'Returns $true when VM .vhdx file is specified with a generation 2 VM' { +# Mock -CommandName Test-VMSecureBoot -MockWith { return $true } +# Test-TargetResource -Name 'Generation2VM' -Generation 2 @testParams | Should -Be $true +# } + +# It 'throws when a VM .vhd file is specified with a generation 2 VM' { +# { Test-TargetResource -Name 'Gen2VM' -VhdPath $stubVhdDisk.Path -Generation 2 } | Should -Throw +# } + +# It 'Returns $true when multiple NICs are assigned in the correct order' { +# Test-TargetResource -Name 'RunningVM' @testParams -SwitchName @($stubNIC1.SwitchName, $stubNIC2.SwitchName) | Should -Be $true +# } + +# It 'Returns $false when multiple NICs are not assigned/assigned in the wrong order' { +# Test-TargetResource -Name 'RunningVM' @testParams -SwitchName @($stubNIC2.SwitchName, $stubNIC1.SwitchName) | Should -Be $false +# } + +# It 'Returns $true when multiple MAC addresses are assigned in the correct order' { +# Test-TargetResource -Name 'RunningVM' @testParams -MACAddress @($stubNIC1.MACAddress, $stubNIC2.MACAddress) | Should -Be $true +# } + +# It 'Returns $false when multiple MAC addresses not assigned/assigned in the wrong order' { +# Test-TargetResource -Name 'RunningVM' @testParams -MACAddress @($stubNIC1.MACAddress, $stubNIC2.MACAddress) | Should -Be $true +# } + +# It 'Returns $true regardless of "SecureBoot" setting on a generation 1 VM' { +# Test-TargetResource -Name 'RunningVM' -SecureBoot $true @testParams | Should -Be $true +# Test-TargetResource -Name 'RunningVM' -SecureBoot $false @testParams | Should -Be $true +# } + +# It 'Returns $true when SecureBoot is On and requested "SecureBoot" = "$true"' { +# Mock -CommandName Test-VMSecureBoot -MockWith { return $true } +# Test-TargetResource -Name 'Generation2VM' -Generation 2 @testParams | Should -Be $true +# } + +# It 'Returns $false when SecureBoot is On and requested "SecureBoot" = "$false"' { +# Mock -CommandName Test-VMSecureBoot -MockWith { return $true } +# Test-TargetResource -Name 'Generation2VM' -SecureBoot $false -Generation 2 @testParams | Should -Be $false +# } + +# It 'Returns $true when VM has snapshot chain' { +# Mock -CommandName Get-VhdHierarchy -MockWith { +# return @($studVhdxDiskSnapshot, $stubVhdxDisk) +# } +# Test-TargetResource -Name 'Generation2VM' -VhdPath $stubVhdxDisk.Path -Verbose | Should -Be $true +# } + +# It 'Returns $false when EnableGuestService is off and requested "EnableGuestService" = "$true"' { +# Test-TargetResource -Name 'RunningVM' -EnableGuestService $true @testParams | Should -Be $false +# } + +# It 'Returns $true when EnableGuestService is off and "EnableGuestService" is not requested"' { +# Test-TargetResource -Name 'RunningVM' @testParams | Should -Be $true +# } + +# Mock -CommandName Get-Command -ParameterFilter { $Name -eq 'Set-VM' -and $Module -eq 'Hyper-V' } -MockWith { +# [pscustomobject]@{ +# parameters = @{ +# # Does not contains parameter AutomaticCheckpointsEnabled +# } +# } +# } +# It 'throws when AutomaticCheckpointsEnabled is configured but not supported' { +# { Test-TargetResource -Name 'VMAutomaticCheckpoinstUnsupported' -AutomaticCheckpointsEnabled $true @testParams } | Should -Throw +# } + +# Mock -CommandName Get-Command -ParameterFilter { $Name -eq 'Set-VM' -and $Module -eq 'Hyper-V' } -MockWith { +# [pscustomobject]@{ +# parameters = @{ +# 'AutomaticCheckpointsEnabled' = '' +# } +# } +# } +# It 'Returns $true when AutomaticCheckpointsEnabled is on and requested "AutomaticCheckpointsEnabled" is not requested' { +# Test-TargetResource -Name 'VMWithAutomaticCheckpoints' @testParams | Should -Be $true +# } +# It 'Returns $true when AutomaticCheckpointsEnabled is on and requested "AutomaticCheckpointsEnabled" = "$true"' { +# Test-TargetResource -Name 'VMWithAutomaticCheckpoints' -AutomaticCheckpointsEnabled $true @testParams | Should -Be $true +# } +# It 'Returns $true when AutomaticCheckpointsEnabled is off and requested "AutomaticCheckpointsEnabled" = "$false"' { +# Test-TargetResource -Name 'VMWithoutAutomaticCheckpoints' -AutomaticCheckpointsEnabled $false @testParams | Should -Be $true +# } +# It 'Returns $false when AutomaticCheckpointsEnabled is off and requested "AutomaticCheckpointsEnabled" = "$true"' { +# Test-TargetResource -Name 'VMWithoutAutomaticCheckpoints' -AutomaticCheckpointsEnabled $true @testParams | Should -Be $false +# } +# It 'Returns $false when AutomaticCheckpointsEnabled is on and requested "AutomaticCheckpointsEnabled" = "$false"' { +# Test-TargetResource -Name 'VMWithAutomaticCheckpoints' -AutomaticCheckpointsEnabled $false @testParams | Should -Be $false +# } + +# It 'Returns $true when EnableGuestService is on and requested "EnableGuestService" = "$true"' { +# Mock -CommandName Get-VMIntegrationService -MockWith { +# $guestServiceInterface = [Microsoft.HyperV.PowerShell.VMIntegrationComponent]::CreateTypeInstance() +# $guestServiceInterface.Enabled = $true +# $guestServiceInterface.Id = $stubGuestServiceInterfaceId + +# return $guestServiceInterface +# } + +# Test-TargetResource -Name 'RunningVM' -EnableGuestService $true @testParams | Should -Be $true +# } + +# It 'throws when Hyper-V Tools are not installed' { +# # This test needs to be the last in the Context otherwise all subsequent Get-Module checks will fail +# Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } +# { Test-TargetResource -Name 'RunningVM' @testParams } | Should -Throw +# } + +# } #end context Validates Test-TargetResource Method + +# Context 'Validates Set-TargetResource Method' { +# $testParams = @{ +# VhdPath = $stubVhdxDisk.Path +# } + +# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'NewVM' } +# Mock -CommandName New-VM -MockWith { +# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() +# $stubVM.Name = 'NewVM' +# $stubVM.Path = $StubVMConfig.FullPath +# $stubVM.Generation = $Generation +# $stubVM.ID = $mockVmGuid +# $stubVM.State = 'Off' + +# return $stubVM +# } + +# Mock -CommandName Set-VM -MockWith { return $true } +# Mock -CommandName Stop-VM -MockWith { return $true } # requires output to be able to pipe something into Remove-VM +# Mock -CommandName Remove-VM -MockWith { return $true } +# Mock -CommandName Set-VMNetworkAdapter -MockWith { return $true } +# Mock -CommandName Get-VMNetworkAdapter -MockWith { return $stubVM.NetworkAdapters.IpAddresses } +# Mock -CommandName Set-VMState -MockWith { return $true } +# Mock -CommandName Set-VMMemory + +# It 'Removes an existing VM when "Ensure" = "Absent"' { +# Set-TargetResource -Name 'RunningVM' -Ensure Absent @testParams +# Assert-MockCalled -CommandName Remove-VM -Scope It +# } + +# It 'Creates and starts a VM VM with disabled dynamic memory that does not exist when "Ensure" = "Present" and "State" = "Running"' { +# Set-TargetResource -Name 'NewVM' -State Running @testParams +# Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It +# Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It +# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 1 -Scope It +# } + +# It 'Creates but does not start a VM with disabled dynamic memory that does not exist when "Ensure" = "Present"' { +# Set-TargetResource -Name 'NewVM' @testParams +# Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It +# Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It +# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It +# } + +# It 'Creates but does not start a VM with disabled dynamic memory when only StartupMemory is specified' { +# Set-TargetResource -Name 'NewVM' @testParams -StartupMemory 4GB +# Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It +# Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It +# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It +# } + +# It 'Creates but does not start a VM with disabled dynamic memory when identical values for startup, minimum and maximum memory are specified' { +# Set-TargetResource -Name 'NewVM' @testParams -StartupMemory 4GB -MinimumMemory 4GB -MaximumMemory 4GB +# Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It +# Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It +# Assert-MockCalled -CommandName Set-VMMemory -Exactly -Times 1 -Scope It +# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It +# } + +# It 'Creates but does not start a VM with enabled dynamic memory because a MinimumMemory value is specified' { +# Set-TargetResource -Name 'NewVM' @testParams -MinimumMemory 512MB +# Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It +# Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It +# Assert-MockCalled -CommandName Set-VMMemory -Exactly -Times 0 -Scope It +# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It +# } + +# It 'Creates but does not start a VM with enabled dynamic memory because a MaximumMemory value is specified' { +# Set-TargetResource -Name 'NewVM' @testParams -MaximumMemory 16GB +# Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It +# Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It +# Assert-MockCalled -CommandName Set-VMMemory -Exactly -Times 0 -Scope It +# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It +# } + +# It 'Does not change VM state when VM "State" = "Running" and requested "State" = "Running"' { +# Set-TargetResource -Name 'RunningVM' -State Running @testParams +# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It +# } + +# It 'Does not change VM state when VM "State" = "Off" and requested "State" = "Off"' { +# Set-TargetResource -Name 'StoppedVM' -State Off @testParams +# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It +# } + +# It 'Changes VM state when existing VM "State" = "Off" and requested "State" = "Running"' { +# Set-TargetResource -Name 'StoppedVM' -State Running @testParams +# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 1 -Scope It +# } + +# It 'Changes VM state when existing VM "State" = "Running" and requested "State" = "Off"' { +# Set-TargetResource -Name 'RunningVM' -State Off @testParams +# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 1 -Scope It +# } + +# It 'Creates a generation 1 VM by default/when not explicitly specified' { +# Set-TargetResource -Name 'NewVM' @testParams +# Assert-MockCalled -CommandName New-VM -ParameterFilter { $Generation -eq 1 } -Scope It +# } + +# It 'Creates a generation 1 VM when explicitly specified' { +# Set-TargetResource -Name 'NewVM' -Generation 1 @testParams +# Assert-MockCalled -CommandName New-VM -ParameterFilter { $Generation -eq 1 } -Scope It +# } + +# It 'Creates a generation 2 VM when explicitly specified' { +# Set-TargetResource -Name 'NewVM' -Generation 2 @testParams +# Assert-MockCalled -CommandName New-VM -ParameterFilter { $Generation -eq 2 } -Scope It +# } + +# It 'Calls "Add-VMNetworkAdapter" for each NIC when creating a new VM' { +# Mock -CommandName Add-VMNetworkAdapter +# Set-TargetResource -Name 'NewVM' @testParams -SwitchName 'Switch1', 'Switch2' +# # The first NIC is assigned during the VM creation +# Assert-MockCalled -CommandName Add-VMNetworkAdapter -Exactly 1 -Scope It +# } + +# It 'Calls "Connect-VMNetworkAdapter" for each existing NIC when updating an existing VM' { +# Mock -CommandName Connect-VMNetworkAdapter +# Set-TargetResource -Name 'StoppedVM' @testParams -SwitchName 'Switch1', 'Switch2' +# # The first NIC is assigned during the VM creation +# Assert-MockCalled -CommandName Connect-VMNetworkAdapter -Exactly 2 -Scope It +# } + +# It 'Calls "Add-VMNetworkAdapter" for each missing NIC when updating an existing VM' { +# Mock -CommandName Connect-VMNetworkAdapter +# Mock -CommandName Add-VMNetworkAdapter +# Set-TargetResource -Name 'StoppedVM' @testParams -SwitchName 'Switch1', 'Switch2', 'Switch3' +# # The first NIC is assigned during the VM creation +# Assert-MockCalled -CommandName Connect-VMNetworkAdapter -Exactly 2 -Scope It +# Assert-MockCalled -CommandName Add-VMNetworkAdapter -Exactly 1 -Scope It +# } + +# It 'Does not change switch assignments if no switch assignments are specified' { +# Mock -CommandName Connect-VMNetworkAdapter +# Set-TargetResource -Name 'StoppedVM' @testParams +# Assert-MockCalled -CommandName Connect-VMNetworkAdapter -Exactly 0 -Scope It +# } + +# It 'Does not change NIC assignments if the switch assisgnments are correct' { +# Mock -CommandName Set-VMNetworkAdapter +# Set-TargetResource -Name 'StoppedVM' @testParams -SwitchName $stubNIC1.SwitchName, $stubNIC2.SwitchName +# Assert-MockCalled -CommandName Set-VMNetworkAdapter -Exactly 0 -Scope It +# } + +# It 'Errors when updating MAC addresses on a running VM and "RestartIfNeeded" = "$false"' { +# { Set-TargetResource -Name 'RunningVM' @testParams -MACAddress 'AABBCCDDEEFE', 'AABBCCDDEEFF' -ErrorAction Stop } | Should -Throw +# } + +# It 'Does not change MAC addresses if no MAC addresses assignments are specified' { +# Mock -CommandName Set-VMNetworkAdapter -ParameterFilter { $StaticMacAddress -ne $null } +# Set-TargetResource -Name 'StoppedVM' @testParams +# Assert-MockCalled -CommandName Set-VMNetworkAdapter -ParameterFilter { $StaticMacAddress -ne $null } -Exactly 0 -Scope It +# } + +# It 'Calls "Set-VMNetworkAdapter" for each MAC address on a stopped VM' { +# Mock -CommandName Set-VMNetworkAdapter +# Set-TargetResource -Name 'StoppedVM' @testParams -MACAddress 'AABBCCDDEEFE', 'AABBCCDDEEFF' +# # The first NIC is assigned during the VM creation +# Assert-MockCalled -CommandName Set-VMNetworkAdapter -Exactly 2 -Scope It +# } + +# It 'Does not change Secure Boot call "Set-VMProperty" when creating a generation 1 VM' { +# Mock -CommandName Set-VMProperty +# Set-TargetResource -Name 'RunningVM' @testParams +# Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 0 -Scope It +# } + +# It 'Does call "Set-VMProperty" when creating a generation 2 VM' { +# Mock -CommandName Test-VMSecureBoot -MockWith { return $true } +# Mock -CommandName Set-VMProperty +# Set-TargetResource -Name 'RunningVM' -Generation 2 -SecureBoot $false @testParams +# Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 1 -Scope It +# } + +# It 'Does not change Secure Boot for generation 1 VM' { +# Mock -CommandName Test-VMSecureBoot -MockWith { return $true } +# Mock -CommandName Set-VMProperty +# Set-TargetResource -Name 'StoppedVM' -SecureBoot $true @testParams +# Set-TargetResource -Name 'StoppedVM' -SecureBoot $false @testParams +# Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 0 -Scope It +# } + +# It 'Does not change Secure Boot for generation 2 VM with VM "SecureBoot" match' { +# Mock -CommandName Test-VMSecureBoot -MockWith { return $true } +# Mock -CommandName Set-VMProperty +# Set-TargetResource -Name 'StoppedVM' -SecureBoot $true -Generation 2 @testParams +# Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 0 -Scope It +# } + +# It 'Does change Secure Boot for generation 2 VM with VM "SecureBoot" mismatch' { +# Mock -CommandName Test-VMSecureBoot -MockWith { return $false } +# Mock -CommandName Set-VMProperty +# Set-TargetResource -Name 'StoppedVM' -SecureBoot $true -Generation 2 @testParams +# Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 1 -Scope It +# } + +# It 'Does call "Enable-VMIntegrationService" when "EnableGuestService" = "$true"' { +# Mock -CommandName Enable-VMIntegrationService +# Set-TargetResource -Name 'RunningVM' -EnableGuestService $true @testParams +# Assert-MockCalled -CommandName Enable-VMIntegrationService -Exactly -Times 1 -Scope It +# } + +# It 'Does call "Disable-VMIntegrationService" when "Guest Service Interface" = "Enabled" and "EnableGuestService" = "$false" specified' { +# Mock -CommandName Disable-VMIntegrationService +# Mock -CommandName Get-VMIntegrationService -MockWith { +# $guestServiceInterface = [Microsoft.HyperV.PowerShell.VMIntegrationComponent]::CreateTypeInstance() +# $guestServiceInterface.Enabled = $true +# $guestServiceInterface.Id = $stubGuestServiceInterfaceId + +# return $guestServiceInterface +# } + +# Set-TargetResource -Name 'RunningVM' -EnableGuestService $false @testParams +# Assert-MockCalled -CommandName Disable-VMIntegrationService -Exactly -Times 1 -Scope It +# } + +# Mock -CommandName Get-Command -ParameterFilter { $Name -eq 'Set-VM' -and $Module -eq 'Hyper-V' } -MockWith { +# [pscustomobject]@{ +# parameters = @{ +# # Does not contain parameter AutomaticCheckpointsEnabled +# } +# } +# } +# It 'throws when AutomaticCheckpointsEnabled is configured but not supported' { +# { Set-TargetResource -Name 'VMAutomaticCheckpointsUnsupported' -AutomaticCheckpointsEnabled $true @testParams } | Should -Throw +# } +# It 'Does not call "Set-VM" when "AutomaticCheckpointsEnabled" is unsupported and unspecified' { +# Set-TargetResource -Name 'VMAutomaticCheckpointsUnsupported' @testParams +# Assert-MockCalled -CommandName Set-VM -Exactly -Times 0 -Scope It +# } + +# Mock -CommandName Get-Command -ParameterFilter { $Name -eq 'Set-VM' -and $Module -eq 'Hyper-V' } -MockWith { +# [pscustomobject]@{ +# parameters = @{ +# 'AutomaticCheckpointsEnabled' = '' +# } +# } +# } +# $AutomaticCheckpointsEnabledTestCases = @( +# @{ +# VMName = 'VMWithAutomaticCheckpoints' +# SetAutomaticCheckpointsEnabled = $true +# Assert = 'Does not call "Set-VM"' +# Times = 0 +# }, +# @{ +# VMName = 'VMWithoutAutomaticCheckpoints' +# SetAutomaticCheckpointsEnabled = $false +# Assert = 'Does not call "Set-VM"' +# Times = 0 +# }, +# @{ +# VMName = 'VMWithAutomaticCheckpoints' +# SetAutomaticCheckpointsEnabled = $false +# Assert = 'Does call "Set-VM"' +# Times = 1 +# }, +# @{ +# VMName = 'VMWithoutAutomaticCheckpoints' +# SetAutomaticCheckpointsEnabled = $true +# Assert = 'Does call "Set-VM"' +# Times = 1 +# } +# ) +# It ' on VM when "AutomaticCheckpointsEnabled" is set to ""' -TestCases $AutomaticCheckpointsEnabledTestCases { +# param +# ( +# $VMName, +# $SetAutomaticCheckpointsEnabled, +# $Times +# ) + +# Set-TargetResource -Name $VMName -AutomaticCheckpointsEnabled $SetAutomaticCheckpointsEnabled @testParams +# Assert-MockCalled -CommandName Set-VM -ParameterFilter { $Name -eq $VMName -and $AutomaticCheckpointsEnabled -eq $SetAutomaticCheckpointsEnabled } -Exactly -Times $Times -Scope It +# } +# It 'Disables dynamic memory of RuningVM if only StartupMemory specified' { +# Mock -CommandName Set-VMProperty +# Set-TargetResource -Name 'RunningVM' -StartupMemory 4GB @testParams +# Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { +# $VMCommand -eq 'Set-VM' -and +# ($ChangeProperty.StaticMemory -eq $true) -and +# ($ChangeProperty.DynamicMemory -eq $false) +# } -Exactly -Times 1 -Scope It +# } + +# It 'Disables dynamic memory of RunningVM if StartupMemory, MinimumMemory and MaximumMemory are specified with the same values' { +# Mock -CommandName Set-VMProperty +# Set-TargetResource -Name 'RunningVM' -StartupMemory 4GB -MinimumMemory 4GB -MaximumMemory 4GB @testParams +# Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { +# $VMCommand -eq 'Set-VM' -and +# ($ChangeProperty.StaticMemory -eq $true) -and +# ($ChangeProperty.DynamicMemory -eq $false) +# } -Exactly -Times 1 -Scope It +# } + +# It 'Enables dynamic memory of RuningVM if MinimumMemory is specified ' { +# Mock -CommandName Set-VMProperty +# Set-TargetResource -Name 'RunningVM' -MinimumMemory 4GB @testParams +# Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { +# $VMCommand -eq 'Set-VM' -and +# ($ChangeProperty.StaticMemory -eq $false) -and +# ($ChangeProperty.DynamicMemory -eq $true) +# } -Exactly -Times 1 -Scope It +# } + +# It 'Enables dynamic memory of RuningVM if MaximumMemory is specified ' { +# Mock -CommandName Set-VMProperty +# Set-TargetResource -Name 'RunningVM' -MaximumMemory 4GB @testParams +# Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { +# $VMCommand -eq 'Set-VM' -and +# ($ChangeProperty.StaticMemory -eq $false) -and +# ($ChangeProperty.DynamicMemory -eq $true) +# } -Exactly -Times 1 -Scope It +# } + +# It 'throws when Hyper-V Tools are not installed' { +# Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } +# { Set-TargetResource -Name 'RunningVM' @testParams } | Should -Throw +# } +# } #end context Validates Set-TargetResource Method + +# Context 'Validates Test-VMSecureBoot Method' { +# BeforeAll { +# Mock -CommandName Get-VM -MockWith { +# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() +# $stubVM.Name = 'NewVM' +# $stubVM.Path = $StubVMConfig.FullPath +# $stubVM.Generation = $Generation +# $stubVM.ID = $mockVmGuid +# $stubVM.State = 'Off' + +# return $stubVM +# } +# } + +# It 'Returns $true when "SecureBoot" = "On"' { +# Mock -CommandName Get-VMFirmware -MockWith { +# return [PSCustomObject] @{ +# SecureBoot = 'On' +# } +# } + +# Test-VMSecureBoot -Name 'TestVM' | Should -Be $true +# } + +# It 'Returns $false when "SecureBoot" = "Off"' { +# Mock -CommandName Get-VMFirmware -MockWith { +# return [PSCustomObject] @{ +# SecureBoot = 'Off' +# } +# } + +# Test-VMSecureBoot -Name 'TestVM' | Should -Be $false +# } + +# } #end context Validates Test-VMSecureBoot Method + +# Context 'Validates Get-VhdHierarchy Method' { +# It 'Does not throw with null parent path (#52)' { +# # Must use a different file extension to ensure existing mocks Get-VhdHierarchy or not called +# $fakeVhdPath = 'BaseVhd.avhdx' + +# Mock -CommandName Get-VHD -ParameterFilter { $Path -eq $fakeVhdPath } -MockWith { +# return [PSCustomObject] @{ +# Path = $fakeVhdPath +# ParentPath = $null +# } +# } + +# { Get-VhdHierarchy -VhdPath $fakeVhdPath } | Should -Not -throw +# } + +# } #end context validates Get-VhdHierarchy +# } #end describe xVMHyper-V +# } #end inmodulescope +# } +# finally +# { +# Invoke-TestCleanup +# } diff --git a/tests/Unit/DSC_VMNetworkAdapter.Tests.ps1 b/tests/Unit/DSC_VMNetworkAdapter.Tests.ps1 index e9fa23a..b07d883 100644 --- a/tests/Unit/DSC_VMNetworkAdapter.Tests.ps1 +++ b/tests/Unit/DSC_VMNetworkAdapter.Tests.ps1 @@ -1,352 +1,352 @@ -$script:dscModuleName = 'HyperVDsc' -$script:dscResourceName = 'DSC_VMNetworkAdapter' - -function Invoke-TestSetup -{ - try - { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' - } - catch [System.IO.FileNotFoundException] - { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' - } - - $script:testEnvironment = Initialize-TestEnvironment ` - -DSCModuleName $script:dscModuleName ` - -DSCResourceName $script:dscResourceName ` - -ResourceType 'Mof' ` - -TestType 'Unit' - - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -} - -function Invoke-TestCleanup -{ - Restore-TestEnvironment -TestEnvironment $script:testEnvironment -} - -Invoke-TestSetup - -try -{ - InModuleScope $script:dscResourceName { - # Create the Mock -CommandName Objects that will be used for running tests - $MockHostAdapter = [PSCustomObject] @{ - Id = 'HostManagement1' - Name = 'Management' - SwitchName = 'HostSwitch' - VMName = 'ManagementOS' - } - - $propertiesStatic = @{ - DHCPEnabled = $false - IpAddress = "192.168.0.1" - Subnet = "255.255.255.0" - } - - $networkSettingsStatic = New-CimInstance -ClassName VMNetworkAdapterNetworkSettings -Property $propertiesStatic -Namespace root/microsoft/windows/desiredstateconfiguration -ClientOnly - - $TestAdapter = [PSObject]@{ - Id = $MockHostAdapter.Id - Name = $MockHostAdapter.Name - SwitchName = $MockHostAdapter.SwitchName - VMName = $MockHostAdapter.VMName - } - - $MockAdapter = [Microsoft.HyperV.PowerShell.VMNetworkAdapterBase]::CreateTypeInstance() - $MockAdapter.Name = $MockHostAdapter.Name - $MockAdapter.SwitchName = $MockHostAdapter.SwitchName - $MockAdapter.VMName = $MockHostAdapter.VMName - $MockAdapter.IsManagementOs = $true - $MockAdapter.MacAddress = '14FEB5C6CE98' - - $MockAdapterVlanUntagged = [PSObject]@{ - OperationMode = 'Untagged' - } - - $MockAdapterVlanTagged = [PSObject]@{ - OperationMode = 'Access' - AccessVlanId = '1' - } - - Describe 'DSC_VMNetworkAdapter\Get-TargetResource' { - Context 'NetAdapter does not exist' { - Mock -CommandName Get-VMNetworkAdapter - Mock -CommandName Get-VMNetworkAdapterVlan - It 'should return ensure as absent' { - $Result = Get-TargetResource ` - @TestAdapter - $Result.Ensure | Should -Be 'Absent' - } - It 'should call the expected mocks' { - Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 - Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 0 - } - } - - Context 'NetAdapter with untagged VLAN exists' { - Mock -CommandName Get-VMNetworkAdapter -MockWith { - $MockAdapter - } - - Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { - $MockAdapterVlanUntagged - } - Mock -CommandName Get-NetworkInformation -MockWith { - return @{ - IpAddress = '10.10.10.10' - Subnet = '255.255.255.0' - DefaultGateway = '10.10.10.1' - DnsServer = @( '10.10.10.1' ) - } - } - - It 'should return adapter properties' { - $Result = Get-TargetResource @TestAdapter - $Result.Ensure | Should -Be 'Present' - $Result.Name | Should -Be $TestAdapter.Name - $Result.SwitchName | Should -Be $TestAdapter.SwitchName - $Result.VMName | Should -Be 'ManagementOS' - $Result.Id | Should -Be $TestAdapter.Id - $Result.VlanId | Should -BeNullOrEmpty - $Result.NetworkSetting | Should -Not -BeNullOrEmpty - } - It 'should call the expected mocks' { - Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 - Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 - } - } - - Context 'NetAdapter with tagged VLAN exists' { - Mock -CommandName Get-VMNetworkAdapter -MockWith { - $MockAdapter - } - - Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { - $MockAdapterVlanTagged - } - - Mock -CommandName Get-NetworkInformation -MockWith { - return @{ - IpAddress = '10.10.10.10' - Subnet = '255.255.255.0' - DefaultGateway = '10.10.10.1' - DnsServer = @( '10.10.10.1', '10.10.10.2' ) - } - } - - It 'should return adapter properties' { - $Result = Get-TargetResource @TestAdapter - $Result.Ensure | Should -Be 'Present' - $Result.Name | Should -Be $TestAdapter.Name - $Result.SwitchName | Should -Be $TestAdapter.SwitchName - $Result.VMName | Should -Be 'ManagementOS' - $Result.Id | Should -Be $TestAdapter.Id - $Result.VlanId | Should -Be '1' - } - It 'should call the expected mocks' { - Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 - Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 - } - } - } - - Describe 'DSC_VMNetworkAdapter\Set-TargetResource' { - $newAdapter = [PSObject]@{ - Id = 'UniqueString' - Name = $TestAdapter.Name - SwitchName = $TestAdapter.SwitchName - VMName = 'VMName' - NetworkSetting = $networkSettingsStatic - Ensure = 'Present' - } - - Context 'Adapter does not exist but should' { - Mock -CommandName Get-VMNetworkAdapter - Mock -CommandName Get-VMNetworkAdapterVlan - Mock -CommandName Add-VMNetworkAdapter -MockWith { - $MockAdapter - } - Mock -CommandName Remove-VMNetworkAdapter - Mock -CommandName Set-VMNetworkAdapterVlan - Mock -CommandName Set-NetworkInformation - - It 'should not throw error' { - { - Set-TargetResource @newAdapter - } | Should -Not -throw - } - - It 'should call expected Mocks' { - Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 - Assert-MockCalled -CommandName Set-VMNetworkAdapterVlan -Exactly 0 - Assert-MockCalled -commandName Add-VMNetworkAdapter -Exactly 1 - Assert-MockCalled -commandName Remove-VMNetworkAdapter -Exactly 0 - Assert-MockCalled -CommandName Set-NetworkInformation -Exactly 1 - } - } - - Context 'Adapter exists but should not exist' { - Mock -CommandName Get-VMNetworkAdapter - Mock -CommandName Add-VMNetworkAdapter - Mock -CommandName Remove-VMNetworkAdapter - Mock -CommandName Set-VMNetworkAdapterVlan - - It 'should not throw error' { - { - $updateAdapter = $newAdapter.Clone() - $updateAdapter.Ensure = 'Absent' - Set-TargetResource @updateAdapter - } | Should -Not -throw - } - It 'should call expected Mocks' { - Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 - Assert-MockCalled -commandName Add-VMNetworkAdapter -Exactly 0 - Assert-MockCalled -commandName Remove-VMNetworkAdapter -Exactly 1 - Assert-MockCalled -CommandName Set-VMNetworkAdapterVlan -Exactly 0 - } - } - } - - Describe 'DSC_VMNetworkAdapter\Test-TargetResource' { - $newAdapter = [PSObject]@{ - Id = 'UniqueString' - Name = $TestAdapter.Name - SwitchName = $TestAdapter.SwitchName - VMName = 'ManagementOS' - Ensure = 'Present' - } - - Context 'Adapter does not exist but should' { - Mock -CommandName Get-VMNetworkAdapter - Mock -CommandName Get-VMNetworkAdapterVlan - - It 'should return false' { - Test-TargetResource @newAdapter | Should -Be $false - } - It 'should call expected Mocks' { - Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 - } - } - - Context 'Adapter exists but should not exist' { - Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } - - It 'should return $false' { - $updateAdapter = $newAdapter.Clone() - $updateAdapter.Ensure = 'Absent' - Test-TargetResource @updateAdapter | Should -Be $false - } - It 'should call expected Mocks' { - Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 - } - } - - Context 'Adapter exists and no action needed without Vlan tag' { - Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } - - It 'should return true' { - $updateAdapter = $newAdapter.Clone() - Test-TargetResource @updateAdapter | Should -Be $true - } - It 'should call expected Mocks' { - Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 - } - } - - Context 'Adapter exists and no action needed with Vlan tag' { - Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } - Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { $MockAdapterVlanTagged } - Mock -CommandName Get-NetworkInformation - - It 'should return true' { - $updateAdapter = $newAdapter.Clone() - $updateAdapter.VMName = "VMName" - $updateAdapter.MacAddress = '14FEB5C6CE98' - $updateAdapter.VlanId = '1' - Test-TargetResource @updateAdapter | Should -Be $true - } - It 'should call expected Mocks' { - Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 - Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 - } - } - - Context 'Adapter exists but Vlan is not tagged' { - Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } - Mock -CommandName Get-VMNetworkAdapterVlan - Mock -CommandName Get-NetworkInformation - - It 'should return false' { - $updateAdapter = $newAdapter.Clone() - $updateAdapter.VMName = "VMName" - $updateAdapter.MacAddress = '14FEB5C6CE98' - $updateAdapter.VlanId = '1' - Test-TargetResource @updateAdapter | Should -Be $false - } - It 'should call expected Mocks' { - Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 - Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 - } - } - - Context 'Adapter exists but Vlan tag is wrong' { - Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } - Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { $MockAdapterVlanTagged } - Mock -CommandName Get-NetworkInformation - - It 'should return false' { - $updateAdapter = $newAdapter.Clone() - $updateAdapter.VMName = "VMName" - $updateAdapter.MacAddress = '14FEB5C6CE98' - $updateAdapter.VlanId = '2' - Test-TargetResource @updateAdapter | Should -Be $false - } - It 'should call expected Mocks' { - Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 - Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 - } - } - - Context 'Adapter does not exist and no action needed' { - Mock -CommandName Get-VMNetworkAdapter - - It 'should return true' { - $updateAdapter = $newAdapter.Clone() - $updateAdapter.Ensure = 'Absent' - Test-TargetResource @updateAdapter | Should -Be $true - } - It 'should call expected Mocks' { - Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 - } - } - - Context 'Adapter exists and network settings are not specified' { - Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } - Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { $MockAdapterVlanTagged } - Mock -CommandName Get-NetworkInformation -MockWith { - @{ DHCPEnabled = $false } - } - - It 'should return false' { - $updateAdapter = $newAdapter.Clone() - $updateAdapter.VMName = "VMName" - $updateAdapter.MacAddress = '14FEB5C6CE98' - Test-TargetResource @updateAdapter | Should -Be $false - } - It 'should call expected Mocks' { - Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 - Assert-MockCalled -commandName Get-NetworkInformation -Exactly 0 - } - } - } - - } - #endregion -} -finally -{ - Invoke-TestCleanup -} +# $script:dscModuleName = 'HyperVDsc' +# $script:dscResourceName = 'DSC_VMNetworkAdapter' + +# function Invoke-TestSetup +# { +# try +# { +# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' +# } +# catch [System.IO.FileNotFoundException] +# { +# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' +# } + +# $script:testEnvironment = Initialize-TestEnvironment ` +# -DSCModuleName $script:dscModuleName ` +# -DSCResourceName $script:dscResourceName ` +# -ResourceType 'Mof' ` +# -TestType 'Unit' + +# # Import the stub functions. +# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +# } + +# function Invoke-TestCleanup +# { +# Restore-TestEnvironment -TestEnvironment $script:testEnvironment +# } + +# Invoke-TestSetup + +# try +# { +# InModuleScope $script:dscResourceName { +# # Create the Mock -CommandName Objects that will be used for running tests +# $MockHostAdapter = [PSCustomObject] @{ +# Id = 'HostManagement1' +# Name = 'Management' +# SwitchName = 'HostSwitch' +# VMName = 'ManagementOS' +# } + +# $propertiesStatic = @{ +# DHCPEnabled = $false +# IpAddress = "192.168.0.1" +# Subnet = "255.255.255.0" +# } + +# $networkSettingsStatic = New-CimInstance -ClassName VMNetworkAdapterNetworkSettings -Property $propertiesStatic -Namespace root/microsoft/windows/desiredstateconfiguration -ClientOnly + +# $TestAdapter = [PSObject]@{ +# Id = $MockHostAdapter.Id +# Name = $MockHostAdapter.Name +# SwitchName = $MockHostAdapter.SwitchName +# VMName = $MockHostAdapter.VMName +# } + +# $MockAdapter = [Microsoft.HyperV.PowerShell.VMNetworkAdapterBase]::CreateTypeInstance() +# $MockAdapter.Name = $MockHostAdapter.Name +# $MockAdapter.SwitchName = $MockHostAdapter.SwitchName +# $MockAdapter.VMName = $MockHostAdapter.VMName +# $MockAdapter.IsManagementOs = $true +# $MockAdapter.MacAddress = '14FEB5C6CE98' + +# $MockAdapterVlanUntagged = [PSObject]@{ +# OperationMode = 'Untagged' +# } + +# $MockAdapterVlanTagged = [PSObject]@{ +# OperationMode = 'Access' +# AccessVlanId = '1' +# } + +# Describe 'DSC_VMNetworkAdapter\Get-TargetResource' { +# Context 'NetAdapter does not exist' { +# Mock -CommandName Get-VMNetworkAdapter +# Mock -CommandName Get-VMNetworkAdapterVlan +# It 'should return ensure as absent' { +# $Result = Get-TargetResource ` +# @TestAdapter +# $Result.Ensure | Should -Be 'Absent' +# } +# It 'should call the expected mocks' { +# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 +# Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 0 +# } +# } + +# Context 'NetAdapter with untagged VLAN exists' { +# Mock -CommandName Get-VMNetworkAdapter -MockWith { +# $MockAdapter +# } + +# Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { +# $MockAdapterVlanUntagged +# } +# Mock -CommandName Get-NetworkInformation -MockWith { +# return @{ +# IpAddress = '10.10.10.10' +# Subnet = '255.255.255.0' +# DefaultGateway = '10.10.10.1' +# DnsServer = @( '10.10.10.1' ) +# } +# } + +# It 'should return adapter properties' { +# $Result = Get-TargetResource @TestAdapter +# $Result.Ensure | Should -Be 'Present' +# $Result.Name | Should -Be $TestAdapter.Name +# $Result.SwitchName | Should -Be $TestAdapter.SwitchName +# $Result.VMName | Should -Be 'ManagementOS' +# $Result.Id | Should -Be $TestAdapter.Id +# $Result.VlanId | Should -BeNullOrEmpty +# $Result.NetworkSetting | Should -Not -BeNullOrEmpty +# } +# It 'should call the expected mocks' { +# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 +# Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 +# } +# } + +# Context 'NetAdapter with tagged VLAN exists' { +# Mock -CommandName Get-VMNetworkAdapter -MockWith { +# $MockAdapter +# } + +# Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { +# $MockAdapterVlanTagged +# } + +# Mock -CommandName Get-NetworkInformation -MockWith { +# return @{ +# IpAddress = '10.10.10.10' +# Subnet = '255.255.255.0' +# DefaultGateway = '10.10.10.1' +# DnsServer = @( '10.10.10.1', '10.10.10.2' ) +# } +# } + +# It 'should return adapter properties' { +# $Result = Get-TargetResource @TestAdapter +# $Result.Ensure | Should -Be 'Present' +# $Result.Name | Should -Be $TestAdapter.Name +# $Result.SwitchName | Should -Be $TestAdapter.SwitchName +# $Result.VMName | Should -Be 'ManagementOS' +# $Result.Id | Should -Be $TestAdapter.Id +# $Result.VlanId | Should -Be '1' +# } +# It 'should call the expected mocks' { +# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 +# Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 +# } +# } +# } + +# Describe 'DSC_VMNetworkAdapter\Set-TargetResource' { +# $newAdapter = [PSObject]@{ +# Id = 'UniqueString' +# Name = $TestAdapter.Name +# SwitchName = $TestAdapter.SwitchName +# VMName = 'VMName' +# NetworkSetting = $networkSettingsStatic +# Ensure = 'Present' +# } + +# Context 'Adapter does not exist but should' { +# Mock -CommandName Get-VMNetworkAdapter +# Mock -CommandName Get-VMNetworkAdapterVlan +# Mock -CommandName Add-VMNetworkAdapter -MockWith { +# $MockAdapter +# } +# Mock -CommandName Remove-VMNetworkAdapter +# Mock -CommandName Set-VMNetworkAdapterVlan +# Mock -CommandName Set-NetworkInformation + +# It 'should not throw error' { +# { +# Set-TargetResource @newAdapter +# } | Should -Not -throw +# } + +# It 'should call expected Mocks' { +# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 +# Assert-MockCalled -CommandName Set-VMNetworkAdapterVlan -Exactly 0 +# Assert-MockCalled -commandName Add-VMNetworkAdapter -Exactly 1 +# Assert-MockCalled -commandName Remove-VMNetworkAdapter -Exactly 0 +# Assert-MockCalled -CommandName Set-NetworkInformation -Exactly 1 +# } +# } + +# Context 'Adapter exists but should not exist' { +# Mock -CommandName Get-VMNetworkAdapter +# Mock -CommandName Add-VMNetworkAdapter +# Mock -CommandName Remove-VMNetworkAdapter +# Mock -CommandName Set-VMNetworkAdapterVlan + +# It 'should not throw error' { +# { +# $updateAdapter = $newAdapter.Clone() +# $updateAdapter.Ensure = 'Absent' +# Set-TargetResource @updateAdapter +# } | Should -Not -throw +# } +# It 'should call expected Mocks' { +# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 +# Assert-MockCalled -commandName Add-VMNetworkAdapter -Exactly 0 +# Assert-MockCalled -commandName Remove-VMNetworkAdapter -Exactly 1 +# Assert-MockCalled -CommandName Set-VMNetworkAdapterVlan -Exactly 0 +# } +# } +# } + +# Describe 'DSC_VMNetworkAdapter\Test-TargetResource' { +# $newAdapter = [PSObject]@{ +# Id = 'UniqueString' +# Name = $TestAdapter.Name +# SwitchName = $TestAdapter.SwitchName +# VMName = 'ManagementOS' +# Ensure = 'Present' +# } + +# Context 'Adapter does not exist but should' { +# Mock -CommandName Get-VMNetworkAdapter +# Mock -CommandName Get-VMNetworkAdapterVlan + +# It 'should return false' { +# Test-TargetResource @newAdapter | Should -Be $false +# } +# It 'should call expected Mocks' { +# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 +# } +# } + +# Context 'Adapter exists but should not exist' { +# Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } + +# It 'should return $false' { +# $updateAdapter = $newAdapter.Clone() +# $updateAdapter.Ensure = 'Absent' +# Test-TargetResource @updateAdapter | Should -Be $false +# } +# It 'should call expected Mocks' { +# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 +# } +# } + +# Context 'Adapter exists and no action needed without Vlan tag' { +# Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } + +# It 'should return true' { +# $updateAdapter = $newAdapter.Clone() +# Test-TargetResource @updateAdapter | Should -Be $true +# } +# It 'should call expected Mocks' { +# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 +# } +# } + +# Context 'Adapter exists and no action needed with Vlan tag' { +# Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } +# Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { $MockAdapterVlanTagged } +# Mock -CommandName Get-NetworkInformation + +# It 'should return true' { +# $updateAdapter = $newAdapter.Clone() +# $updateAdapter.VMName = "VMName" +# $updateAdapter.MacAddress = '14FEB5C6CE98' +# $updateAdapter.VlanId = '1' +# Test-TargetResource @updateAdapter | Should -Be $true +# } +# It 'should call expected Mocks' { +# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 +# Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 +# } +# } + +# Context 'Adapter exists but Vlan is not tagged' { +# Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } +# Mock -CommandName Get-VMNetworkAdapterVlan +# Mock -CommandName Get-NetworkInformation + +# It 'should return false' { +# $updateAdapter = $newAdapter.Clone() +# $updateAdapter.VMName = "VMName" +# $updateAdapter.MacAddress = '14FEB5C6CE98' +# $updateAdapter.VlanId = '1' +# Test-TargetResource @updateAdapter | Should -Be $false +# } +# It 'should call expected Mocks' { +# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 +# Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 +# } +# } + +# Context 'Adapter exists but Vlan tag is wrong' { +# Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } +# Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { $MockAdapterVlanTagged } +# Mock -CommandName Get-NetworkInformation + +# It 'should return false' { +# $updateAdapter = $newAdapter.Clone() +# $updateAdapter.VMName = "VMName" +# $updateAdapter.MacAddress = '14FEB5C6CE98' +# $updateAdapter.VlanId = '2' +# Test-TargetResource @updateAdapter | Should -Be $false +# } +# It 'should call expected Mocks' { +# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 +# Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 +# } +# } + +# Context 'Adapter does not exist and no action needed' { +# Mock -CommandName Get-VMNetworkAdapter + +# It 'should return true' { +# $updateAdapter = $newAdapter.Clone() +# $updateAdapter.Ensure = 'Absent' +# Test-TargetResource @updateAdapter | Should -Be $true +# } +# It 'should call expected Mocks' { +# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 +# } +# } + +# Context 'Adapter exists and network settings are not specified' { +# Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } +# Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { $MockAdapterVlanTagged } +# Mock -CommandName Get-NetworkInformation -MockWith { +# @{ DHCPEnabled = $false } +# } + +# It 'should return false' { +# $updateAdapter = $newAdapter.Clone() +# $updateAdapter.VMName = "VMName" +# $updateAdapter.MacAddress = '14FEB5C6CE98' +# Test-TargetResource @updateAdapter | Should -Be $false +# } +# It 'should call expected Mocks' { +# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 +# Assert-MockCalled -commandName Get-NetworkInformation -Exactly 0 +# } +# } +# } + +# } +# #endregion +# } +# finally +# { +# Invoke-TestCleanup +# } diff --git a/tests/Unit/DSC_VMProcessor.Tests.ps1 b/tests/Unit/DSC_VMProcessor.Tests.ps1 index f261477..354e4fa 100644 --- a/tests/Unit/DSC_VMProcessor.Tests.ps1 +++ b/tests/Unit/DSC_VMProcessor.Tests.ps1 @@ -1,294 +1,294 @@ -$script:dscModuleName = 'HyperVDsc' -$script:dscResourceName = 'DSC_VMProcessor' +# $script:dscModuleName = 'HyperVDsc' +# $script:dscResourceName = 'DSC_VMProcessor' -function Invoke-TestSetup -{ - try - { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' - } - catch [System.IO.FileNotFoundException] - { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' - } +# function Invoke-TestSetup +# { +# try +# { +# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' +# } +# catch [System.IO.FileNotFoundException] +# { +# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' +# } - $script:testEnvironment = Initialize-TestEnvironment ` - -DSCModuleName $script:dscModuleName ` - -DSCResourceName $script:dscResourceName ` - -ResourceType 'Mof' ` - -TestType 'Unit' +# $script:testEnvironment = Initialize-TestEnvironment ` +# -DSCModuleName $script:dscModuleName ` +# -DSCResourceName $script:dscResourceName ` +# -ResourceType 'Mof' ` +# -TestType 'Unit' - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -} - -function Invoke-TestCleanup -{ - Restore-TestEnvironment -TestEnvironment $script:testEnvironment -} - -Invoke-TestSetup - -try -{ - InModuleScope $script:dscResourceName { - - $testVMName = 'UnitTestVM' - $testResourcePoolName = 'Unit Test Resource Pool' - - Describe 'DSC_VMProcessor\Get-TargetResource' { - - $fakeVMProcessor = @{ - EnableHostResourceProtection = $true - } - - # Guard mocks - Mock -CommandName Assert-Module - - It 'Should return a [System.Collections.Hashtable] object type' { - Mock -CommandName Get-VMProcessor { return $fakeVMProcessor } - - $result = Get-TargetResource -VMName $testVMName - - $result -is [System.Collections.Hashtable] | Should -Be $true - } - - It 'Should assert Hyper-V module is installed' { - Mock -CommandName Assert-Module - Mock -CommandName Get-VMProcessor { return $fakeVMProcessor } - - $null = Get-TargetResource -VMName $testVMName - - Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It - } - - It 'Should throw when VM processor is not found' { - Mock -CommandName Get-Module { return $true } - Mock -CommandName Get-VMProcessor { Write-Error 'Not Found' } - { $null = Get-TargetResource -VMName $testVMName } | Should -Throw 'Not Found' - } - } # descrive Get-TargetResource - - Describe 'DSC_VMProcessor\Test-TargetResource' { - - # Guard mocks - Mock -CommandName Assert-Module - Mock -CommandName Assert-TargetResourceParameter - - $fakeTargetResource = @{ - VMName = $testVMName - EnableHostResourceProtection = $true - ExposeVirtualizationExtensions = $true - HwThreadCountPerCore = 1 - Maximum = 99 - MaximumCountPerNumaNode = 4 - MaximumCountPerNumaSocket = 1 - RelativeWeight = 99 - Reserve = 0 - ResourcePoolName = $testResourcePoolName - CompatibilityForMigrationEnabled = $false - CompatibilityForOlderOperatingSystemsEnabled = $false - } - - It 'Should return a [System.Boolean] object type' { - Mock -CommandName Get-TargetResource { return $fakeTargetResource } - - $result = Test-TargetResource -VMName $testVMName - - $result -is [System.Boolean] | Should -Be $true - } - - It 'Should assert Hyper-V module is installed' { - Mock -CommandName Get-VMProcessor { return $fakeVMProcessor } - - $null = Test-TargetResource -VMName $testVMName - - Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It - } - - It 'Should assert parameter values are valid' { - Mock -CommandName Get-VMProcessor { return $fakeVMProcessor } - - $null = Test-TargetResource -VMName $testVMName - - Assert-MockCalled -CommandName Assert-TargetResourceParameter -Scope It - } - - $parameterNames = @( - 'EnableHostResourceProtection', - 'ExposeVirtualizationExtensions', - 'HwThreadCountPerCore', - 'Maximum', - 'MaximumCountPerNumaNode', - 'MaximumCountPerNumaSocket', - 'RelativeWeight', - 'Reserve', - 'ResourcePoolName', - 'CompatibilityForMigrationEnabled', - 'CompatibilityForOlderOperatingSystemsEnabled' - ) - - # Test each individual parameter value separately - foreach ($parameterName in $parameterNames) - { - $parameterValue = $fakeTargetResource[$parameterName] - $testTargetResourceParams = @{ - VMName = $testVMName - } - - # Pass value verbatim so it should always pass first - It "Should pass when parameter '$parameterName' is correct" { - $testTargetResourceParams[$parameterName] = $parameterValue - - $result = Test-TargetResource @testTargetResourceParams - - $result | Should -Be $true - } - - if ($parameterValue -is [System.Boolean]) - { - # Invert parameter value to cause a test failure - $testTargetResourceParams[$parameterName] = -not $parameterValue - } - elseif ($parameterValue -is [System.String]) - { - # Repeat string to cause a test failure - $testTargetResourceParams[$parameterName] = "$parameterValue$parameterValue" - } - elseif ($parameterValue -is [System.Int32] -or $parameterValue -is [System.Int64]) - { - # Add one to cause a test failure - $testTargetResourceParams[$parameterName] = $parameterValue + 1 - } - - It "Should fail when parameter '$parameterName' is incorrect" { - $result = Test-TargetResource @testTargetResourceParams - - $result | Should -Be $false - } - } - } # describe Test-TargetResource - - Describe 'DSC_VMProcessor\Set-TargetResource' { - # Guard mocks - Mock -CommandName Assert-Module - Mock -CommandName Assert-TargetResourceParameter - Mock -CommandName Get-VM - Mock -CommandName Set-VMProcessor - Mock -CommandName Set-VMProperty - - It 'Should assert Hyper-V module is installed' { - $null = Set-TargetResource -VMName $testVMName - - Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It - } - - It 'Should assert parameter values are valid' { - $null = Set-TargetResource -VMName $testVMName - - Assert-MockCalled -CommandName Assert-TargetResourceParameter -Scope It - } - - $restartRequiredParameters = @{ - 'ExposeVirtualizationExtensions' = $false - 'CompatibilityForMigrationEnabled' = $true - 'CompatibilityForOlderOperatingSystemsEnabled' = $true - 'HwThreadCountPerCore' = 2 - 'MaximumCountPerNumaNode' = 2 - 'MaximumCountPerNumaSocket' = 2 - 'ResourcePoolName' = $testResourcePoolName - } - - foreach ($parameter in $restartRequiredParameters.GetEnumerator()) - { - $setTargetResourceParams = @{ - VMName = $testVMName - $parameter.Name = $parameter.Value - } - - It "Should not throw when VM is off, '$($parameter.Name)' is specified and 'RestartIfNeeded' is False" { - Mock -CommandName Get-VM -MockWith { - return @{ - State = 'Off' - } - } - - { Set-TargetResource @setTargetResourceParams } | Should -Not -throw - } - - It "Should throw when VM is running, '$($parameter.Name)' is specified and 'RestartIfNeeded' is False" { - Mock -CommandName Get-VM { return @{ State = 'Running' } } - - { Set-TargetResource @setTargetResourceParams } | Should -Throw - } - - It "Should shutdown VM when running, '$($parameter.Name)' is specified and 'RestartIfNeeded' is True" { - Mock -CommandName Get-VM { return @{ State = 'Running' } } - - Set-TargetResource @setTargetResourceParams -RestartIfNeeded $true - - Assert-MockCalled -CommandName Set-VMProperty -Scope It -Exactly 1 - } - } - - $noRestartRequiredParameters = @{ - 'EnableHostResourceProtection' = $true - 'Maximum' = 50 - 'RelativeWeight' = 50 - 'Reserve' = 50 - } - - foreach ($parameter in $noRestartRequiredParameters.GetEnumerator()) - { - $setTargetResourceParams = @{ - VMName = $testVMName - $parameter.Name = $parameter.Value - } - - It "Should not shutdown VM running and '$($parameter.Name) is specified" { - Mock -CommandName Get-VM -MockWith { - return @{ - State = 'Running' - } - } - - Set-TargetResource @setTargetResourceParams - - Assert-MockCalled -CommandName Set-VMProcessor -Scope It -Exactly 1 - Assert-MockCalled -CommandName Set-VMProperty -Scope It -Exactly 0 - } - } - } # describe Set-TargetResource - - Describe 'DSC_VMProcessor\Assert-TargetResourceParameter' { - - # Return Windows Server 2012 R2/Windows 8.1 Update 1 - Mock -CommandName Get-CimInstance { return @{ BuildNumber = '9600' } } - - It "Should not throw when parameter 'ResourcePoolName' is specified on 2012 R2 host" { - { Assert-TargetResourceParameter -ResourcePoolName 'TestPool' } | Should -Not -throw - } - - $server2016OnlyParameters = @{ - EnableHostResourceProtection = $true - ExposeVirtualizationExtensions = $true - HwThreadCountPerCore = 1 - } - - foreach ($parameter in $server2016OnlyParameters.GetEnumerator()) - { - $assertTargetResourceParameterParams = @{ - $parameter.Name = $parameter.Value - } - - It "Should throw when parameter '$($parameter.Name)' is specified on 2012 R2 host" { - { Assert-TargetResourceParameter @assertTargetResourceParameterParams } | Should -Throw '14393' - } - } - } # describe Assert-TargetResourceParameter - } # InModuleScope -} -finally -{ - Invoke-TestCleanup -} +# # Import the stub functions. +# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +# } + +# function Invoke-TestCleanup +# { +# Restore-TestEnvironment -TestEnvironment $script:testEnvironment +# } + +# Invoke-TestSetup + +# try +# { +# InModuleScope $script:dscResourceName { + +# $testVMName = 'UnitTestVM' +# $testResourcePoolName = 'Unit Test Resource Pool' + +# Describe 'DSC_VMProcessor\Get-TargetResource' { + +# $fakeVMProcessor = @{ +# EnableHostResourceProtection = $true +# } + +# # Guard mocks +# Mock -CommandName Assert-Module + +# It 'Should return a [System.Collections.Hashtable] object type' { +# Mock -CommandName Get-VMProcessor { return $fakeVMProcessor } + +# $result = Get-TargetResource -VMName $testVMName + +# $result -is [System.Collections.Hashtable] | Should -Be $true +# } + +# It 'Should assert Hyper-V module is installed' { +# Mock -CommandName Assert-Module +# Mock -CommandName Get-VMProcessor { return $fakeVMProcessor } + +# $null = Get-TargetResource -VMName $testVMName + +# Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It +# } + +# It 'Should throw when VM processor is not found' { +# Mock -CommandName Get-Module { return $true } +# Mock -CommandName Get-VMProcessor { Write-Error 'Not Found' } +# { $null = Get-TargetResource -VMName $testVMName } | Should -Throw 'Not Found' +# } +# } # descrive Get-TargetResource + +# Describe 'DSC_VMProcessor\Test-TargetResource' { + +# # Guard mocks +# Mock -CommandName Assert-Module +# Mock -CommandName Assert-TargetResourceParameter + +# $fakeTargetResource = @{ +# VMName = $testVMName +# EnableHostResourceProtection = $true +# ExposeVirtualizationExtensions = $true +# HwThreadCountPerCore = 1 +# Maximum = 99 +# MaximumCountPerNumaNode = 4 +# MaximumCountPerNumaSocket = 1 +# RelativeWeight = 99 +# Reserve = 0 +# ResourcePoolName = $testResourcePoolName +# CompatibilityForMigrationEnabled = $false +# CompatibilityForOlderOperatingSystemsEnabled = $false +# } + +# It 'Should return a [System.Boolean] object type' { +# Mock -CommandName Get-TargetResource { return $fakeTargetResource } + +# $result = Test-TargetResource -VMName $testVMName + +# $result -is [System.Boolean] | Should -Be $true +# } + +# It 'Should assert Hyper-V module is installed' { +# Mock -CommandName Get-VMProcessor { return $fakeVMProcessor } + +# $null = Test-TargetResource -VMName $testVMName + +# Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It +# } + +# It 'Should assert parameter values are valid' { +# Mock -CommandName Get-VMProcessor { return $fakeVMProcessor } + +# $null = Test-TargetResource -VMName $testVMName + +# Assert-MockCalled -CommandName Assert-TargetResourceParameter -Scope It +# } + +# $parameterNames = @( +# 'EnableHostResourceProtection', +# 'ExposeVirtualizationExtensions', +# 'HwThreadCountPerCore', +# 'Maximum', +# 'MaximumCountPerNumaNode', +# 'MaximumCountPerNumaSocket', +# 'RelativeWeight', +# 'Reserve', +# 'ResourcePoolName', +# 'CompatibilityForMigrationEnabled', +# 'CompatibilityForOlderOperatingSystemsEnabled' +# ) + +# # Test each individual parameter value separately +# foreach ($parameterName in $parameterNames) +# { +# $parameterValue = $fakeTargetResource[$parameterName] +# $testTargetResourceParams = @{ +# VMName = $testVMName +# } + +# # Pass value verbatim so it should always pass first +# It "Should pass when parameter '$parameterName' is correct" { +# $testTargetResourceParams[$parameterName] = $parameterValue + +# $result = Test-TargetResource @testTargetResourceParams + +# $result | Should -Be $true +# } + +# if ($parameterValue -is [System.Boolean]) +# { +# # Invert parameter value to cause a test failure +# $testTargetResourceParams[$parameterName] = -not $parameterValue +# } +# elseif ($parameterValue -is [System.String]) +# { +# # Repeat string to cause a test failure +# $testTargetResourceParams[$parameterName] = "$parameterValue$parameterValue" +# } +# elseif ($parameterValue -is [System.Int32] -or $parameterValue -is [System.Int64]) +# { +# # Add one to cause a test failure +# $testTargetResourceParams[$parameterName] = $parameterValue + 1 +# } + +# It "Should fail when parameter '$parameterName' is incorrect" { +# $result = Test-TargetResource @testTargetResourceParams + +# $result | Should -Be $false +# } +# } +# } # describe Test-TargetResource + +# Describe 'DSC_VMProcessor\Set-TargetResource' { +# # Guard mocks +# Mock -CommandName Assert-Module +# Mock -CommandName Assert-TargetResourceParameter +# Mock -CommandName Get-VM +# Mock -CommandName Set-VMProcessor +# Mock -CommandName Set-VMProperty + +# It 'Should assert Hyper-V module is installed' { +# $null = Set-TargetResource -VMName $testVMName + +# Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It +# } + +# It 'Should assert parameter values are valid' { +# $null = Set-TargetResource -VMName $testVMName + +# Assert-MockCalled -CommandName Assert-TargetResourceParameter -Scope It +# } + +# $restartRequiredParameters = @{ +# 'ExposeVirtualizationExtensions' = $false +# 'CompatibilityForMigrationEnabled' = $true +# 'CompatibilityForOlderOperatingSystemsEnabled' = $true +# 'HwThreadCountPerCore' = 2 +# 'MaximumCountPerNumaNode' = 2 +# 'MaximumCountPerNumaSocket' = 2 +# 'ResourcePoolName' = $testResourcePoolName +# } + +# foreach ($parameter in $restartRequiredParameters.GetEnumerator()) +# { +# $setTargetResourceParams = @{ +# VMName = $testVMName +# $parameter.Name = $parameter.Value +# } + +# It "Should not throw when VM is off, '$($parameter.Name)' is specified and 'RestartIfNeeded' is False" { +# Mock -CommandName Get-VM -MockWith { +# return @{ +# State = 'Off' +# } +# } + +# { Set-TargetResource @setTargetResourceParams } | Should -Not -throw +# } + +# It "Should throw when VM is running, '$($parameter.Name)' is specified and 'RestartIfNeeded' is False" { +# Mock -CommandName Get-VM { return @{ State = 'Running' } } + +# { Set-TargetResource @setTargetResourceParams } | Should -Throw +# } + +# It "Should shutdown VM when running, '$($parameter.Name)' is specified and 'RestartIfNeeded' is True" { +# Mock -CommandName Get-VM { return @{ State = 'Running' } } + +# Set-TargetResource @setTargetResourceParams -RestartIfNeeded $true + +# Assert-MockCalled -CommandName Set-VMProperty -Scope It -Exactly 1 +# } +# } + +# $noRestartRequiredParameters = @{ +# 'EnableHostResourceProtection' = $true +# 'Maximum' = 50 +# 'RelativeWeight' = 50 +# 'Reserve' = 50 +# } + +# foreach ($parameter in $noRestartRequiredParameters.GetEnumerator()) +# { +# $setTargetResourceParams = @{ +# VMName = $testVMName +# $parameter.Name = $parameter.Value +# } + +# It "Should not shutdown VM running and '$($parameter.Name) is specified" { +# Mock -CommandName Get-VM -MockWith { +# return @{ +# State = 'Running' +# } +# } + +# Set-TargetResource @setTargetResourceParams + +# Assert-MockCalled -CommandName Set-VMProcessor -Scope It -Exactly 1 +# Assert-MockCalled -CommandName Set-VMProperty -Scope It -Exactly 0 +# } +# } +# } # describe Set-TargetResource + +# Describe 'DSC_VMProcessor\Assert-TargetResourceParameter' { + +# # Return Windows Server 2012 R2/Windows 8.1 Update 1 +# Mock -CommandName Get-CimInstance { return @{ BuildNumber = '9600' } } + +# It "Should not throw when parameter 'ResourcePoolName' is specified on 2012 R2 host" { +# { Assert-TargetResourceParameter -ResourcePoolName 'TestPool' } | Should -Not -throw +# } + +# $server2016OnlyParameters = @{ +# EnableHostResourceProtection = $true +# ExposeVirtualizationExtensions = $true +# HwThreadCountPerCore = 1 +# } + +# foreach ($parameter in $server2016OnlyParameters.GetEnumerator()) +# { +# $assertTargetResourceParameterParams = @{ +# $parameter.Name = $parameter.Value +# } + +# It "Should throw when parameter '$($parameter.Name)' is specified on 2012 R2 host" { +# { Assert-TargetResourceParameter @assertTargetResourceParameterParams } | Should -Throw '14393' +# } +# } +# } # describe Assert-TargetResourceParameter +# } # InModuleScope +# } +# finally +# { +# Invoke-TestCleanup +# } diff --git a/tests/Unit/DSC_VMScsiController.Tests.ps1 b/tests/Unit/DSC_VMScsiController.Tests.ps1 index 7b455b5..a917f2a 100644 --- a/tests/Unit/DSC_VMScsiController.Tests.ps1 +++ b/tests/Unit/DSC_VMScsiController.Tests.ps1 @@ -1,350 +1,350 @@ -$script:dscModuleName = 'HyperVDsc' -$script:dscResourceName = 'DSC_VMScsiController' +# $script:dscModuleName = 'HyperVDsc' +# $script:dscResourceName = 'DSC_VMScsiController' -function Invoke-TestSetup -{ - try - { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' - } - catch [System.IO.FileNotFoundException] - { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' - } +# function Invoke-TestSetup +# { +# try +# { +# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' +# } +# catch [System.IO.FileNotFoundException] +# { +# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' +# } - $script:testEnvironment = Initialize-TestEnvironment ` - -DSCModuleName $script:dscModuleName ` - -DSCResourceName $script:dscResourceName ` - -ResourceType 'Mof' ` - -TestType 'Unit' +# $script:testEnvironment = Initialize-TestEnvironment ` +# -DSCModuleName $script:dscModuleName ` +# -DSCResourceName $script:dscResourceName ` +# -ResourceType 'Mof' ` +# -TestType 'Unit' - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -} +# # Import the stub functions. +# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +# } -function Invoke-TestCleanup -{ - Restore-TestEnvironment -TestEnvironment $script:testEnvironment -} +# function Invoke-TestCleanup +# { +# Restore-TestEnvironment -TestEnvironment $script:testEnvironment +# } -Invoke-TestSetup +# Invoke-TestSetup -try -{ - InModuleScope $script:dscResourceName { +# try +# { +# InModuleScope $script:dscResourceName { - $testVMName = 'UnitTestVM' +# $testVMName = 'UnitTestVM' - Describe 'DSC_VMScsiController\Get-TargetResource' { +# Describe 'DSC_VMScsiController\Get-TargetResource' { - $stubScsiController = @{ - VMName = $testVMName - ControllerNumber = 0 - } +# $stubScsiController = @{ +# VMName = $testVMName +# ControllerNumber = 0 +# } - # Guard mocks - Mock -CommandName Assert-Module +# # Guard mocks +# Mock -CommandName Assert-Module - It 'Should return a [System.Collections.Hashtable] object type' { - Mock -CommandName Get-VMScsiController { return $stubScsiController } +# It 'Should return a [System.Collections.Hashtable] object type' { +# Mock -CommandName Get-VMScsiController { return $stubScsiController } - $result = Get-TargetResource -VMName $testVMName -ControllerNumber 0 +# $result = Get-TargetResource -VMName $testVMName -ControllerNumber 0 - $result -is [System.Collections.Hashtable] | Should -Be $true - } +# $result -is [System.Collections.Hashtable] | Should -Be $true +# } - It 'Should return "Present" when controller is attached' { - Mock -CommandName Get-VMScsiController { return $stubScsiController } +# It 'Should return "Present" when controller is attached' { +# Mock -CommandName Get-VMScsiController { return $stubScsiController } - $result = Get-TargetResource -VMName $testVMName -ControllerNumber 0 +# $result = Get-TargetResource -VMName $testVMName -ControllerNumber 0 - $result.Ensure | Should -Be 'Present' - } +# $result.Ensure | Should -Be 'Present' +# } - It 'Should return "Absent" when controller is not attached' { - Mock -CommandName Get-VMScsiController +# It 'Should return "Absent" when controller is not attached' { +# Mock -CommandName Get-VMScsiController - $result = Get-TargetResource -VMName $testVMName -ControllerNumber 0 - - $result.Ensure | Should -Be 'Absent' - } +# $result = Get-TargetResource -VMName $testVMName -ControllerNumber 0 + +# $result.Ensure | Should -Be 'Absent' +# } - It 'Should assert Hyper-V module is installed' { - Mock -CommandName Assert-Module - Mock -CommandName Get-VMScsiController +# It 'Should assert Hyper-V module is installed' { +# Mock -CommandName Assert-Module +# Mock -CommandName Get-VMScsiController - $null = Get-TargetResource -VMName $testVMName -ControllerNumber 0 - - Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It - } - } # describe Get-TargetResource - - Describe 'DSC_VMScsiController\Test-TargetResource' { +# $null = Get-TargetResource -VMName $testVMName -ControllerNumber 0 + +# Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It +# } +# } # describe Get-TargetResource + +# Describe 'DSC_VMScsiController\Test-TargetResource' { - # Guard mocks - Mock -CommandName Assert-Module +# # Guard mocks +# Mock -CommandName Assert-Module - $stubTargetResource = @{ - VMName = $testVMName - ControllerNumber = 0 - Ensure = 'Present' - } - - It 'Should return a [System.Boolean] object type' { - Mock -CommandName Get-TargetResource { return $stubTargetResource } - $testTargetResourceParams = @{ - VMName = $testVMName - ControllerNumber = 0 - } - - $result = Test-TargetResource @testTargetResourceParams - - $result -is [System.Boolean] | Should -Be $true - } - - It "Should pass when parameter 'Ensure' is correct" { - Mock -CommandName Get-TargetResource { return $stubTargetResource } - $testTargetResourceParams = @{ - VMName = $testVMName - ControllerNumber = 0 - Ensure = $stubTargetResource['Ensure'] - } +# $stubTargetResource = @{ +# VMName = $testVMName +# ControllerNumber = 0 +# Ensure = 'Present' +# } + +# It 'Should return a [System.Boolean] object type' { +# Mock -CommandName Get-TargetResource { return $stubTargetResource } +# $testTargetResourceParams = @{ +# VMName = $testVMName +# ControllerNumber = 0 +# } + +# $result = Test-TargetResource @testTargetResourceParams + +# $result -is [System.Boolean] | Should -Be $true +# } + +# It "Should pass when parameter 'Ensure' is correct" { +# Mock -CommandName Get-TargetResource { return $stubTargetResource } +# $testTargetResourceParams = @{ +# VMName = $testVMName +# ControllerNumber = 0 +# Ensure = $stubTargetResource['Ensure'] +# } - $result = Test-TargetResource @testTargetResourceParams +# $result = Test-TargetResource @testTargetResourceParams - $result | Should -Be $true - } +# $result | Should -Be $true +# } - It "Should fail when parameter 'Ensure' is incorrect" { - Mock -CommandName Get-TargetResource { return $stubTargetResource } - $testTargetResourceParams = @{ - VMName = $testVMName - ControllerNumber = 0 - Ensure = 'Absent' - } - - $result = Test-TargetResource @testTargetResourceParams +# It "Should fail when parameter 'Ensure' is incorrect" { +# Mock -CommandName Get-TargetResource { return $stubTargetResource } +# $testTargetResourceParams = @{ +# VMName = $testVMName +# ControllerNumber = 0 +# Ensure = 'Absent' +# } + +# $result = Test-TargetResource @testTargetResourceParams - $result | Should -Be $false - } - } # describe Test-TargetResource +# $result | Should -Be $false +# } +# } # describe Test-TargetResource - Describe 'DSC_VMScsiController\Set-TargetResource' { - # Guard mocks - Mock -CommandName Assert-Module - Mock -CommandName Get-VMScsiController - Mock -CommandName Add-VMScsiController - Mock -CommandName Remove-VMScsiController - Mock -CommandName Remove-VMHardDiskDrive - Mock -CommandName Set-VMState - - It 'Should assert Hyper-V module is installed' { - Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } - $setTargetResourceParams = @{ - VMName = $testVMName - ControllerNumber = 0 - RestartIfNeeded = $true - } - - $null = Set-TargetResource @setTargetResourceParams - - Assert-MockCalled -CommandName Assert-Module - } - - It 'Should throw if "RestartIfNeeded" is not specified and VM is "Running"' { - Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } - $setTargetResourceParams = @{ - VMName = $testVMName - ControllerNumber = 0 - } - - { Set-TargetResource @setTargetResourceParams } | Should -Throw 'RestartIfNeeded' - } - - It 'Should not throw if "RestartIfNeeded" is not specified and VM is "Off"' { - Mock -CommandName Get-VMHyperV { return @{ State = 'Off' } } - $setTargetResourceParams = @{ - VMName = $testVMName - ControllerNumber = 0 - } - - { Set-TargetResource @setTargetResourceParams } | Should -Not -throw - } - - It 'Should call "Set-VMState" to stop running VM' { - Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } - $setTargetResourceParams = @{ - VMName = $testVMName - ControllerNumber = 0 - RestartIfNeeded = $true - } - - $null = Set-TargetResource @setTargetResourceParams - - Assert-MockCalled -CommandName Set-VMState -ParameterFilter { $State -eq 'Off' } -Scope It - } - - It 'Should call "Set-VMState" to restore VM to its previous state' { - $testVMState = 'Paused' - Mock -CommandName Get-VMHyperV { return @{ State = $testVMState } } - $setTargetResourceParams = @{ - VMName = $testVMName - ControllerNumber = 0 - RestartIfNeeded = $true - } - - $null = Set-TargetResource @setTargetResourceParams - - Assert-MockCalled -CommandName Set-VMState -ParameterFilter { $State -eq $testVMState } -Scope It - } - - It 'Should add single controller when it does not exist' { - Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } - Mock -CommandName Get-VMScsiController - $setTargetResourceParams = @{ - VMName = $testVMName - ControllerNumber = 0 - RestartIfNeeded = $true - } - - $null = Set-TargetResource @setTargetResourceParams - - Assert-MockCalled -CommandName Add-VMScsiController -Scope It -Exactly 1 - } - - It 'Should add single controller when one already exists' { - Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } - $fakeVMScsiController = [PSCustomObject] @{ ControllerNumber = 0 } - Mock -CommandName Get-VMScsiController { return $fakeVMScsiController } - $setTargetResourceParams = @{ - VMName = $testVMName - ControllerNumber = 1 - RestartIfNeeded = $true - } - - $null = Set-TargetResource @setTargetResourceParams - - Assert-MockCalled -CommandName Add-VMScsiController -Scope It -Exactly 1 - } - - It 'Should throw when adding controller when intermediate controller(s) do not exist' { - Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } - Mock -CommandName Get-VMScsiController - $setTargetResourceParams = @{ - VMName = $testVMName - ControllerNumber = 1 - RestartIfNeeded = $true - } - - { Set-TargetResource @setTargetResourceParams } | Should -Throw 'Cannot add controller' - } - - It 'Should remove controller when Ensure = "Absent"' { - Mock -CommandName Get-VMHyperV { - return @{ - State = 'Running' - } - } - - $stubHardDiskDrive = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() - $stubHardDiskDrive.CimSession = New-MockObject -Type CimSession - $stubHardDiskDrive.Path = 'TestDrive:\disk1.vhdx' - $stubHardDiskDrive.ControllerLocation = 0 - $stubHardDiskDrive.ControllerNumber = 0 - $stubHardDiskDrive.ControllerType = 'SCSI' - - $mockVMScsiController = [Microsoft.HyperV.PowerShell.VMScsiController]::CreateTypeInstance() - $mockVMScsiController.Drives = @( - $stubHardDiskDrive - ) - - # Mock getting all the available controllers - Mock -CommandName Get-VMScsiController -MockWith { - return @( - 'mockController1' - 'mockController2' - ) - } - - # Mock getting the specific controller with ControllerNumber -eq 1 - Mock -CommandName Get-VMScsiController -MockWith { - return $mockVMScsiController - } -ParameterFilter { - $ControllerNumber -eq 1 - } - - $setTargetResourceParams = @{ - VMName = $testVMName - ControllerNumber = 1 - RestartIfNeeded = $true - Ensure = 'Absent' - } - - $null = Set-TargetResource @setTargetResourceParams -WarningAction SilentlyContinue - - Assert-MockCalled -CommandName Remove-VMScsiController -Scope It - } - - It 'Should remove all attached disks when Ensure = "Absent"' { - Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } - - $stubHardDiskDrive1 = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() - $stubHardDiskDrive1.CimSession = New-MockObject -Type CimSession - $stubHardDiskDrive1.Name = 'Hard Drive on SCSI controller number 0 at location 0' - $stubHardDiskDrive1.Path = 'TestDrive:\disk1.vhdx' - $stubHardDiskDrive1.ControllerLocation = 0 - $stubHardDiskDrive1.ControllerNumber = 0 - $stubHardDiskDrive1.ControllerType = 'SCSI' - - $stubHardDiskDrive2 = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() - $stubHardDiskDrive2.CimSession = New-MockObject -Type CimSession - $stubHardDiskDrive2.Name = 'Hard Drive on SCSI controller number 0 at location 1' - $stubHardDiskDrive2.Path = 'TestDrive:\disk2.vhdx' - $stubHardDiskDrive2.ControllerLocation = 0 - $stubHardDiskDrive2.ControllerNumber = 0 - $stubHardDiskDrive2.ControllerType = 'SCSI' - - $mockVMScsiController = [Microsoft.HyperV.PowerShell.VMScsiController]::CreateTypeInstance() - $mockVMScsiController.Drives = @( - $stubHardDiskDrive1 - $stubHardDiskDrive2 - ) - - Mock -CommandName Get-VMScsiController { return $mockVMScsiController } - - $setTargetResourceParams = @{ - VMName = $testVMName - ControllerNumber = 0 - RestartIfNeeded = $true - Ensure = 'Absent' - } - - $null = Set-TargetResource @setTargetResourceParams -WarningAction SilentlyContinue - - Assert-MockCalled -CommandName Remove-VMHardDiskDrive -Scope It -Exactly ($mockVMScsiController.Drives.Count) - } - - It 'Should throw removing a controller when additional/subsequent controller(s) exist' { - Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } - $fakeVMScsiControllers = @( - [PSCustomObject] @{ ControllerNumber = 0 } - [PSCustomObject] @{ ControllerNumber = 1 } - ) - Mock -CommandName Get-VMScsiController { return $fakeVMScsiControllers } - $setTargetResourceParams = @{ - VMName = $testVMName - ControllerNumber = 0 - RestartIfNeeded = $true - Ensure = 'Absent' - } - - { Set-TargetResource @setTargetResourceParams } | Should -Throw 'Cannot remove controller' - } - - } # describe Set-TargetResource - } # InModuleScope -} -finally -{ - Invoke-TestCleanup -} +# Describe 'DSC_VMScsiController\Set-TargetResource' { +# # Guard mocks +# Mock -CommandName Assert-Module +# Mock -CommandName Get-VMScsiController +# Mock -CommandName Add-VMScsiController +# Mock -CommandName Remove-VMScsiController +# Mock -CommandName Remove-VMHardDiskDrive +# Mock -CommandName Set-VMState + +# It 'Should assert Hyper-V module is installed' { +# Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } +# $setTargetResourceParams = @{ +# VMName = $testVMName +# ControllerNumber = 0 +# RestartIfNeeded = $true +# } + +# $null = Set-TargetResource @setTargetResourceParams + +# Assert-MockCalled -CommandName Assert-Module +# } + +# It 'Should throw if "RestartIfNeeded" is not specified and VM is "Running"' { +# Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } +# $setTargetResourceParams = @{ +# VMName = $testVMName +# ControllerNumber = 0 +# } + +# { Set-TargetResource @setTargetResourceParams } | Should -Throw 'RestartIfNeeded' +# } + +# It 'Should not throw if "RestartIfNeeded" is not specified and VM is "Off"' { +# Mock -CommandName Get-VMHyperV { return @{ State = 'Off' } } +# $setTargetResourceParams = @{ +# VMName = $testVMName +# ControllerNumber = 0 +# } + +# { Set-TargetResource @setTargetResourceParams } | Should -Not -throw +# } + +# It 'Should call "Set-VMState" to stop running VM' { +# Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } +# $setTargetResourceParams = @{ +# VMName = $testVMName +# ControllerNumber = 0 +# RestartIfNeeded = $true +# } + +# $null = Set-TargetResource @setTargetResourceParams + +# Assert-MockCalled -CommandName Set-VMState -ParameterFilter { $State -eq 'Off' } -Scope It +# } + +# It 'Should call "Set-VMState" to restore VM to its previous state' { +# $testVMState = 'Paused' +# Mock -CommandName Get-VMHyperV { return @{ State = $testVMState } } +# $setTargetResourceParams = @{ +# VMName = $testVMName +# ControllerNumber = 0 +# RestartIfNeeded = $true +# } + +# $null = Set-TargetResource @setTargetResourceParams + +# Assert-MockCalled -CommandName Set-VMState -ParameterFilter { $State -eq $testVMState } -Scope It +# } + +# It 'Should add single controller when it does not exist' { +# Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } +# Mock -CommandName Get-VMScsiController +# $setTargetResourceParams = @{ +# VMName = $testVMName +# ControllerNumber = 0 +# RestartIfNeeded = $true +# } + +# $null = Set-TargetResource @setTargetResourceParams + +# Assert-MockCalled -CommandName Add-VMScsiController -Scope It -Exactly 1 +# } + +# It 'Should add single controller when one already exists' { +# Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } +# $fakeVMScsiController = [PSCustomObject] @{ ControllerNumber = 0 } +# Mock -CommandName Get-VMScsiController { return $fakeVMScsiController } +# $setTargetResourceParams = @{ +# VMName = $testVMName +# ControllerNumber = 1 +# RestartIfNeeded = $true +# } + +# $null = Set-TargetResource @setTargetResourceParams + +# Assert-MockCalled -CommandName Add-VMScsiController -Scope It -Exactly 1 +# } + +# It 'Should throw when adding controller when intermediate controller(s) do not exist' { +# Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } +# Mock -CommandName Get-VMScsiController +# $setTargetResourceParams = @{ +# VMName = $testVMName +# ControllerNumber = 1 +# RestartIfNeeded = $true +# } + +# { Set-TargetResource @setTargetResourceParams } | Should -Throw 'Cannot add controller' +# } + +# It 'Should remove controller when Ensure = "Absent"' { +# Mock -CommandName Get-VMHyperV { +# return @{ +# State = 'Running' +# } +# } + +# $stubHardDiskDrive = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() +# $stubHardDiskDrive.CimSession = New-MockObject -Type CimSession +# $stubHardDiskDrive.Path = 'TestDrive:\disk1.vhdx' +# $stubHardDiskDrive.ControllerLocation = 0 +# $stubHardDiskDrive.ControllerNumber = 0 +# $stubHardDiskDrive.ControllerType = 'SCSI' + +# $mockVMScsiController = [Microsoft.HyperV.PowerShell.VMScsiController]::CreateTypeInstance() +# $mockVMScsiController.Drives = @( +# $stubHardDiskDrive +# ) + +# # Mock getting all the available controllers +# Mock -CommandName Get-VMScsiController -MockWith { +# return @( +# 'mockController1' +# 'mockController2' +# ) +# } + +# # Mock getting the specific controller with ControllerNumber -eq 1 +# Mock -CommandName Get-VMScsiController -MockWith { +# return $mockVMScsiController +# } -ParameterFilter { +# $ControllerNumber -eq 1 +# } + +# $setTargetResourceParams = @{ +# VMName = $testVMName +# ControllerNumber = 1 +# RestartIfNeeded = $true +# Ensure = 'Absent' +# } + +# $null = Set-TargetResource @setTargetResourceParams -WarningAction SilentlyContinue + +# Assert-MockCalled -CommandName Remove-VMScsiController -Scope It +# } + +# It 'Should remove all attached disks when Ensure = "Absent"' { +# Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } + +# $stubHardDiskDrive1 = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() +# $stubHardDiskDrive1.CimSession = New-MockObject -Type CimSession +# $stubHardDiskDrive1.Name = 'Hard Drive on SCSI controller number 0 at location 0' +# $stubHardDiskDrive1.Path = 'TestDrive:\disk1.vhdx' +# $stubHardDiskDrive1.ControllerLocation = 0 +# $stubHardDiskDrive1.ControllerNumber = 0 +# $stubHardDiskDrive1.ControllerType = 'SCSI' + +# $stubHardDiskDrive2 = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() +# $stubHardDiskDrive2.CimSession = New-MockObject -Type CimSession +# $stubHardDiskDrive2.Name = 'Hard Drive on SCSI controller number 0 at location 1' +# $stubHardDiskDrive2.Path = 'TestDrive:\disk2.vhdx' +# $stubHardDiskDrive2.ControllerLocation = 0 +# $stubHardDiskDrive2.ControllerNumber = 0 +# $stubHardDiskDrive2.ControllerType = 'SCSI' + +# $mockVMScsiController = [Microsoft.HyperV.PowerShell.VMScsiController]::CreateTypeInstance() +# $mockVMScsiController.Drives = @( +# $stubHardDiskDrive1 +# $stubHardDiskDrive2 +# ) + +# Mock -CommandName Get-VMScsiController { return $mockVMScsiController } + +# $setTargetResourceParams = @{ +# VMName = $testVMName +# ControllerNumber = 0 +# RestartIfNeeded = $true +# Ensure = 'Absent' +# } + +# $null = Set-TargetResource @setTargetResourceParams -WarningAction SilentlyContinue + +# Assert-MockCalled -CommandName Remove-VMHardDiskDrive -Scope It -Exactly ($mockVMScsiController.Drives.Count) +# } + +# It 'Should throw removing a controller when additional/subsequent controller(s) exist' { +# Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } +# $fakeVMScsiControllers = @( +# [PSCustomObject] @{ ControllerNumber = 0 } +# [PSCustomObject] @{ ControllerNumber = 1 } +# ) +# Mock -CommandName Get-VMScsiController { return $fakeVMScsiControllers } +# $setTargetResourceParams = @{ +# VMName = $testVMName +# ControllerNumber = 0 +# RestartIfNeeded = $true +# Ensure = 'Absent' +# } + +# { Set-TargetResource @setTargetResourceParams } | Should -Throw 'Cannot remove controller' +# } + +# } # describe Set-TargetResource +# } # InModuleScope +# } +# finally +# { +# Invoke-TestCleanup +# } diff --git a/tests/Unit/DSC_VMSwitch_BandwidthReservationMode.Tests.ps1 b/tests/Unit/DSC_VMSwitch_BandwidthReservationMode.Tests.ps1 index 95aee4a..55a0aa5 100644 --- a/tests/Unit/DSC_VMSwitch_BandwidthReservationMode.Tests.ps1 +++ b/tests/Unit/DSC_VMSwitch_BandwidthReservationMode.Tests.ps1 @@ -1,479 +1,479 @@ -$script:dscModuleName = 'HyperVDsc' -$script:dscResourceName = 'DSC_VMSwitch' - -function Invoke-TestSetup -{ - try - { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' - } - catch [System.IO.FileNotFoundException] - { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' - } - - $script:testEnvironment = Initialize-TestEnvironment ` - -DSCModuleName $script:dscModuleName ` - -DSCResourceName $script:dscResourceName ` - -ResourceType 'Mof' ` - -TestType 'Unit' - - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -} - -function Invoke-TestCleanup -{ - Restore-TestEnvironment -TestEnvironment $script:testEnvironment -} - -Invoke-TestSetup - -try -{ - InModuleScope $script:dscResourceName { - - <# - 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)] - [System.String] - $Name, - - [Parameter(Mandatory = $true)] - [ValidateSet('Default', 'Weight', 'Absolute', 'None', 'NA')] - [System.String] - $BandwidthReservationMode, - - [Parameter()] - [System.Boolean] - $AllowManagementOS = $false - ) - - $mockedVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() - $mockedVMSwitch.Name = $Name - $mockedVMSwitch.SwitchType = 'External' - $mockedVMSwitch.AllowManagementOS = $AllowManagementOS - $mockedVMSwitch.NetAdapterInterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver' - - if ($BandwidthReservationMode -ne 'NA') - { - $mockedVMSwitch.BandwidthReservationMode = $BandwidthReservationMode - } - - return $mockedVMSwitch - } - - Describe 'Validates Get-TargetResource Function' { - <# - Mocks Get-VMSwitch and will return $script:mockedVMSwitch which is - a variable that is created during most It statements to mock a VMSwitch - #> - Mock -CommandName Get-VMSwitch -MockWith { - param - ( - [System.String] - $ErrorAction - ) - - if ($ErrorAction -eq 'Stop' -and $script:mockedVMSwitch -eq $null) - { - throw [System.Management.Automation.ActionPreferenceStopException]'No switch can be found by given criteria.' - } - - return $script:mockedVMSwitch - } - - # 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 - } - - # Create all the test cases for Get-TargetResource - $getTestCases = @() - foreach ($brmMode in $BANDWIDTH_RESERVATION_MODES) { - $getTestCases += @{ - CurrentName = $brmMode + 'BRM' - CurrentBandwidthReservationMode = $brmMode - } - } - - # Test Get-TargetResource with the test cases created above - It 'Current switch''s BandwidthReservationMode is set to ' -TestCases $getTestCases { - param - ( - [Parameter()] - [System.String] - $CurrentName, - - [Parameter()] - [System.String] - $CurrentBandwidthReservationMode - ) - - # Set the mocked VMSwitch to be returned from Get-VMSwitch based on the input from $getTestCases - $script: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 'script' -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 - $script: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 "Default" - - Remove-Variable -Scope 'script' -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 - } - } - - Describe 'Validates Test-TargetResource Function' { - <# - Mocks Get-VMSwitch and will return $script:mockedVMSwitch which is - a variable that is created during most It statements to mock a VMSwitch - #> - Mock -CommandName Get-VMSwitch -MockWith { - param ( - [System.String] - $ErrorAction - ) - - if ($ErrorAction -eq 'Stop' -and $script:mockedVMSwitch -eq $null) - { - throw [System.Management.Automation.ActionPreferenceStopException]'No switch can be found by given criteria.' - } - - return $script:mockedVMSwitch - } - - # 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 -CommandName Get-OSVersion -MockWith { - return [Version]::Parse('6.3.9600') - } - - # Create all the test cases for Get-TargetResource - $getTestCases = @() - foreach ($brmMode in $BANDWIDTH_RESERVATION_MODES) - { - $getTestCases += @{ - CurrentName = $brmMode + 'BRM' - CurrentBandwidthReservationMode = $brmMode - } - } - - # Test Test-TargetResource with the test cases created above - It 'Current Name "" | Current BandwidthReservationMode set to "" | Desired BandwidthReservationMode set to "" | Ensure ""' -TestCases $testSetTestCases { - param - ( - [Parameter()] - [System.String] - $CurrentName, - - [Parameter()] - [System.String] - $CurrentBandwidthReservationMode, - - [Parameter()] - [System.String] - $DesiredName, - - [Parameter()] - [System.String] - $DesiredBandwidthReservationMode, - - [Parameter()] - [System.String] - $Ensure, - - [Parameter()] - [System.Boolean] - $ExpectedResult - ) - - # Set the mocked VMSwitch to be returned from Get-VMSwitch if the switch exists - if ($CurrentName) - { - $script: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 'script' -Name 'mockedVMSwitch' -ErrorAction 'SilentlyContinue' - } - - Mock -CommandName Get-OSVersion -MockWith { - return [Version]::Parse('6.1.7601') - } - - # Test Test-TargetResource when the version of Windows doesn't support BandwidthReservationMode - It 'Invalid Operating System Exception' { - $errorMessage = $script:localizedData.BandwidthReservationModeError - - {Test-TargetResource -Name 'WeightBRM' -Type 'External' -NetAdapterName 'SomeNIC' -AllowManagementOS $true -BandwidthReservationMode 'Weight' -Ensure 'Present'} | Should -Throw $errorMessage - } - - It 'Passes when "BandwidthReservationMode" does not match but is not specified (#48)' { - $script:mockedVMSwitch = New-MockedVMSwitch -Name 'SomeSwitch' -BandwidthReservationMode 'Absolute' - $targetResource = Test-TargetResource -Name 'SomeSwitch' -Type 'Internal' -Ensure 'Present' - $targetResource | Should -Be $true - } - } - - Describe 'Validates Set-TargetResource Function' { - <# - Mocks Get-VMSwitch and will return $script:mockedVMSwitch which is - a variable that is created during most It statements to mock a VMSwitch - #> - Mock -CommandName Get-VMSwitch -MockWith { - param - ( - [System.String] - $Name, - - [System.String] - $SwitchType, - - [System.String] - $ErrorAction - ) - - if ($ErrorAction -eq 'Stop' -and $script:mockedVMSwitch -eq $null) - { - throw [System.Management.Automation.ActionPreferenceStopException]'No switch can be found by given criteria.' - } - - return $script:mockedVMSwitch - } - - <# - Mocks New-VMSwitch and will assign a mocked switch to $script:mockedVMSwitch. This returns $script:mockedVMSwitch - which is a variable that is created during most It statements to mock a VMSwitch - #> - Mock -CommandName New-VMSwitch -MockWith { - param - ( - [System.String] - $Name, - - [System.String] - $NetAdapterName, - - [System.String] - $MinimumBandwidthMode, - - [System.Boolean] - $AllowManagementOS - ) - - $script:mockedVMSwitch = New-MockedVMSwitch -Name $Name -BandwidthReservationMode $MinimumBandwidthMode -AllowManagementOS $AllowManagementOS - return $script:mockedVMSwitch - } - - <# - Mocks Set-VMSwitch and will modify $script:mockedVMSwitch which is - a variable that is created during most It statements to mock a VMSwitch - #> - Mock -CommandName Set-VMSwitch -MockWith { - param - ( - [System.Boolean] - $AllowManagementOS - ) - - if ($AllowManagementOS) - { - $script:mockedVMSwitch['AllowManagementOS'] = $AllowManagementOS - } - } - - <# - Mocks Remove-VMSwitch and will remove the variable $script:mockedVMSwitch which is - a variable that is created during most It statements to mock a VMSwitch - #> - Mock -CommandName Remove-VMSwitch -MockWith { - $script: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 -CommandName Get-OSVersion -MockWith { - return [Version]::Parse('6.3.9600') - } - - It 'Current Name "" | Current BandwidthReservationMode set to "" | Desired BandwidthReservationMode set to "" | Ensure ""' -TestCases $testSetTestCases { - param - ( - [Parameter()] - [System.String] - $CurrentName, - - [Parameter()] - [System.String] - $CurrentBandwidthReservationMode, - - [Parameter()] - [System.String] - $DesiredName, - - [Parameter()] - [System.String] - $DesiredBandwidthReservationMode, - - [Parameter()] - [System.String] - $Ensure, - - [Parameter()] - [System.Boolean] - $ExpectedResult - ) - - if ($CurrentName) - { - # Set the mocked VMSwitch to be returned from Get-VMSwitch if the switch exists - $script:mockedVMSwitch = New-MockedVMSwitch -Name $CurrentName -BandwidthReservationMode $CurrentBandwidthReservationMode -AllowManagementOS $true - } - else - { - if ($Ensure -eq 'Absent') - { - # This is called when Ensure = 'Absent'. TO make sure there is a VMSwitch to remove. - $script:mockedVMSwitch = New-MockedVMSwitch -Name $DesiredName -BandwidthReservationMode $DesiredBandwidthReservationMode -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 'script' -Name 'mockedVMSwitch' -ErrorAction 'SilentlyContinue' - } - - # Test Set-TargetResource when the version of Windows doesn't support BandwidthReservationMode - It 'Invalid Operating System Exception' { - Mock -CommandName Get-OSVersion -MockWith { - return [Version]::Parse('6.1.7601') - } - - $errorMessage = $script:localizedData.BandwidthReservationModeError - - {Set-TargetResource -Name 'WeightBRM' -Type 'External' -NetAdapterName 'SomeNIC' -AllowManagementOS $true -BandwidthReservationMode 'Weight' -Ensure 'Present'} | Should -Throw $errorMessage - } - } - } -} -finally -{ - Invoke-TestCleanup -} +# $script:dscModuleName = 'HyperVDsc' +# $script:dscResourceName = 'DSC_VMSwitch' + +# function Invoke-TestSetup +# { +# try +# { +# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' +# } +# catch [System.IO.FileNotFoundException] +# { +# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' +# } + +# $script:testEnvironment = Initialize-TestEnvironment ` +# -DSCModuleName $script:dscModuleName ` +# -DSCResourceName $script:dscResourceName ` +# -ResourceType 'Mof' ` +# -TestType 'Unit' + +# # Import the stub functions. +# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +# } + +# function Invoke-TestCleanup +# { +# Restore-TestEnvironment -TestEnvironment $script:testEnvironment +# } + +# Invoke-TestSetup + +# try +# { +# InModuleScope $script:dscResourceName { + +# <# +# 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)] +# [System.String] +# $Name, + +# [Parameter(Mandatory = $true)] +# [ValidateSet('Default', 'Weight', 'Absolute', 'None', 'NA')] +# [System.String] +# $BandwidthReservationMode, + +# [Parameter()] +# [System.Boolean] +# $AllowManagementOS = $false +# ) + +# $mockedVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() +# $mockedVMSwitch.Name = $Name +# $mockedVMSwitch.SwitchType = 'External' +# $mockedVMSwitch.AllowManagementOS = $AllowManagementOS +# $mockedVMSwitch.NetAdapterInterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver' + +# if ($BandwidthReservationMode -ne 'NA') +# { +# $mockedVMSwitch.BandwidthReservationMode = $BandwidthReservationMode +# } + +# return $mockedVMSwitch +# } + +# Describe 'Validates Get-TargetResource Function' { +# <# +# Mocks Get-VMSwitch and will return $script:mockedVMSwitch which is +# a variable that is created during most It statements to mock a VMSwitch +# #> +# Mock -CommandName Get-VMSwitch -MockWith { +# param +# ( +# [System.String] +# $ErrorAction +# ) + +# if ($ErrorAction -eq 'Stop' -and $script:mockedVMSwitch -eq $null) +# { +# throw [System.Management.Automation.ActionPreferenceStopException]'No switch can be found by given criteria.' +# } + +# return $script:mockedVMSwitch +# } + +# # 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 +# } + +# # Create all the test cases for Get-TargetResource +# $getTestCases = @() +# foreach ($brmMode in $BANDWIDTH_RESERVATION_MODES) { +# $getTestCases += @{ +# CurrentName = $brmMode + 'BRM' +# CurrentBandwidthReservationMode = $brmMode +# } +# } + +# # Test Get-TargetResource with the test cases created above +# It 'Current switch''s BandwidthReservationMode is set to ' -TestCases $getTestCases { +# param +# ( +# [Parameter()] +# [System.String] +# $CurrentName, + +# [Parameter()] +# [System.String] +# $CurrentBandwidthReservationMode +# ) + +# # Set the mocked VMSwitch to be returned from Get-VMSwitch based on the input from $getTestCases +# $script: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 'script' -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 +# $script: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 "Default" + +# Remove-Variable -Scope 'script' -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 +# } +# } + +# Describe 'Validates Test-TargetResource Function' { +# <# +# Mocks Get-VMSwitch and will return $script:mockedVMSwitch which is +# a variable that is created during most It statements to mock a VMSwitch +# #> +# Mock -CommandName Get-VMSwitch -MockWith { +# param ( +# [System.String] +# $ErrorAction +# ) + +# if ($ErrorAction -eq 'Stop' -and $script:mockedVMSwitch -eq $null) +# { +# throw [System.Management.Automation.ActionPreferenceStopException]'No switch can be found by given criteria.' +# } + +# return $script:mockedVMSwitch +# } + +# # 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 -CommandName Get-OSVersion -MockWith { +# return [Version]::Parse('6.3.9600') +# } + +# # Create all the test cases for Get-TargetResource +# $getTestCases = @() +# foreach ($brmMode in $BANDWIDTH_RESERVATION_MODES) +# { +# $getTestCases += @{ +# CurrentName = $brmMode + 'BRM' +# CurrentBandwidthReservationMode = $brmMode +# } +# } + +# # Test Test-TargetResource with the test cases created above +# It 'Current Name "" | Current BandwidthReservationMode set to "" | Desired BandwidthReservationMode set to "" | Ensure ""' -TestCases $testSetTestCases { +# param +# ( +# [Parameter()] +# [System.String] +# $CurrentName, + +# [Parameter()] +# [System.String] +# $CurrentBandwidthReservationMode, + +# [Parameter()] +# [System.String] +# $DesiredName, + +# [Parameter()] +# [System.String] +# $DesiredBandwidthReservationMode, + +# [Parameter()] +# [System.String] +# $Ensure, + +# [Parameter()] +# [System.Boolean] +# $ExpectedResult +# ) + +# # Set the mocked VMSwitch to be returned from Get-VMSwitch if the switch exists +# if ($CurrentName) +# { +# $script: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 'script' -Name 'mockedVMSwitch' -ErrorAction 'SilentlyContinue' +# } + +# Mock -CommandName Get-OSVersion -MockWith { +# return [Version]::Parse('6.1.7601') +# } + +# # Test Test-TargetResource when the version of Windows doesn't support BandwidthReservationMode +# It 'Invalid Operating System Exception' { +# $errorMessage = $script:localizedData.BandwidthReservationModeError + +# {Test-TargetResource -Name 'WeightBRM' -Type 'External' -NetAdapterName 'SomeNIC' -AllowManagementOS $true -BandwidthReservationMode 'Weight' -Ensure 'Present'} | Should -Throw $errorMessage +# } + +# It 'Passes when "BandwidthReservationMode" does not match but is not specified (#48)' { +# $script:mockedVMSwitch = New-MockedVMSwitch -Name 'SomeSwitch' -BandwidthReservationMode 'Absolute' +# $targetResource = Test-TargetResource -Name 'SomeSwitch' -Type 'Internal' -Ensure 'Present' +# $targetResource | Should -Be $true +# } +# } + +# Describe 'Validates Set-TargetResource Function' { +# <# +# Mocks Get-VMSwitch and will return $script:mockedVMSwitch which is +# a variable that is created during most It statements to mock a VMSwitch +# #> +# Mock -CommandName Get-VMSwitch -MockWith { +# param +# ( +# [System.String] +# $Name, + +# [System.String] +# $SwitchType, + +# [System.String] +# $ErrorAction +# ) + +# if ($ErrorAction -eq 'Stop' -and $script:mockedVMSwitch -eq $null) +# { +# throw [System.Management.Automation.ActionPreferenceStopException]'No switch can be found by given criteria.' +# } + +# return $script:mockedVMSwitch +# } + +# <# +# Mocks New-VMSwitch and will assign a mocked switch to $script:mockedVMSwitch. This returns $script:mockedVMSwitch +# which is a variable that is created during most It statements to mock a VMSwitch +# #> +# Mock -CommandName New-VMSwitch -MockWith { +# param +# ( +# [System.String] +# $Name, + +# [System.String] +# $NetAdapterName, + +# [System.String] +# $MinimumBandwidthMode, + +# [System.Boolean] +# $AllowManagementOS +# ) + +# $script:mockedVMSwitch = New-MockedVMSwitch -Name $Name -BandwidthReservationMode $MinimumBandwidthMode -AllowManagementOS $AllowManagementOS +# return $script:mockedVMSwitch +# } + +# <# +# Mocks Set-VMSwitch and will modify $script:mockedVMSwitch which is +# a variable that is created during most It statements to mock a VMSwitch +# #> +# Mock -CommandName Set-VMSwitch -MockWith { +# param +# ( +# [System.Boolean] +# $AllowManagementOS +# ) + +# if ($AllowManagementOS) +# { +# $script:mockedVMSwitch['AllowManagementOS'] = $AllowManagementOS +# } +# } + +# <# +# Mocks Remove-VMSwitch and will remove the variable $script:mockedVMSwitch which is +# a variable that is created during most It statements to mock a VMSwitch +# #> +# Mock -CommandName Remove-VMSwitch -MockWith { +# $script: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 -CommandName Get-OSVersion -MockWith { +# return [Version]::Parse('6.3.9600') +# } + +# It 'Current Name "" | Current BandwidthReservationMode set to "" | Desired BandwidthReservationMode set to "" | Ensure ""' -TestCases $testSetTestCases { +# param +# ( +# [Parameter()] +# [System.String] +# $CurrentName, + +# [Parameter()] +# [System.String] +# $CurrentBandwidthReservationMode, + +# [Parameter()] +# [System.String] +# $DesiredName, + +# [Parameter()] +# [System.String] +# $DesiredBandwidthReservationMode, + +# [Parameter()] +# [System.String] +# $Ensure, + +# [Parameter()] +# [System.Boolean] +# $ExpectedResult +# ) + +# if ($CurrentName) +# { +# # Set the mocked VMSwitch to be returned from Get-VMSwitch if the switch exists +# $script:mockedVMSwitch = New-MockedVMSwitch -Name $CurrentName -BandwidthReservationMode $CurrentBandwidthReservationMode -AllowManagementOS $true +# } +# else +# { +# if ($Ensure -eq 'Absent') +# { +# # This is called when Ensure = 'Absent'. TO make sure there is a VMSwitch to remove. +# $script:mockedVMSwitch = New-MockedVMSwitch -Name $DesiredName -BandwidthReservationMode $DesiredBandwidthReservationMode -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 'script' -Name 'mockedVMSwitch' -ErrorAction 'SilentlyContinue' +# } + +# # Test Set-TargetResource when the version of Windows doesn't support BandwidthReservationMode +# It 'Invalid Operating System Exception' { +# Mock -CommandName Get-OSVersion -MockWith { +# return [Version]::Parse('6.1.7601') +# } + +# $errorMessage = $script:localizedData.BandwidthReservationModeError + +# {Set-TargetResource -Name 'WeightBRM' -Type 'External' -NetAdapterName 'SomeNIC' -AllowManagementOS $true -BandwidthReservationMode 'Weight' -Ensure 'Present'} | Should -Throw $errorMessage +# } +# } +# } +# } +# finally +# { +# Invoke-TestCleanup +# } diff --git a/tests/Unit/DSC_VMSwitch_EnableEmbeddedTeaming.Tests.ps1 b/tests/Unit/DSC_VMSwitch_EnableEmbeddedTeaming.Tests.ps1 index c691353..c450da2 100644 --- a/tests/Unit/DSC_VMSwitch_EnableEmbeddedTeaming.Tests.ps1 +++ b/tests/Unit/DSC_VMSwitch_EnableEmbeddedTeaming.Tests.ps1 @@ -1,494 +1,494 @@ -$script:dscModuleName = 'HyperVDsc' -$script:dscResourceName = 'DSC_VMSwitch' - -function Invoke-TestSetup -{ - try - { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' - } - catch [System.IO.FileNotFoundException] - { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' - } - - $script:testEnvironment = Initialize-TestEnvironment ` - -DSCModuleName $script:dscModuleName ` - -DSCResourceName $script:dscResourceName ` - -ResourceType 'Mof' ` - -TestType 'Unit' - - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -} - -function Invoke-TestCleanup -{ - Restore-TestEnvironment -TestEnvironment $script:testEnvironment -} - -Invoke-TestSetup - -try -{ - InModuleScope $script:dscResourceName { - # A helper function to mock a VMSwitch - function New-MockedVMSwitch - { - param - ( - [Parameter(Mandatory = $true)] - [System.String] - $Name, - - [Parameter(Mandatory = $true)] - [ValidateSet('Default', 'Weight', 'Absolute', 'None', 'NA')] - [System.String] - $BandwidthReservationMode, - - [Parameter()] - [ValidateSet('Dynamic','HyperVPort')] - [System.String] - $LoadBalancingAlgorithm, - - [Parameter()] - [System.Boolean] - $AllowManagementOS = $false - ) - - $mockedVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() - $mockedVMSwitch.Name = $Name - $mockedVMSwitch.SwitchType = 'External' - $mockedVMSwitch.AllowManagementOS = $AllowManagementOS - $mockedVMSwitch.NetAdapterInterfaceDescriptions = 'Microsoft Network Adapter Multiplexor Driver' - - if ($BandwidthReservationMode -ne 'NA') - { - $mockedVMSwitch.BandwidthReservationMode = $BandwidthReservationMode - } - - if ($PSBoundParameters.ContainsKey('LoadBalancingAlgorithm')) - { - $mockedVMSwitch.LoadBalancingAlgorithm = $LoadBalancingAlgorithm - } - - return $mockedVMSwitch - } - - Describe "DSC_VMSwitch" { - <# - Mocks Get-VMSwitch and will return $script:mockedVMSwitch which is - a variable that is created during most It statements to mock a VMSwitch - #> - Mock -CommandName Get-VMSwitch -MockWith { - if ($ErrorAction -eq 'Stop' -and $script:mockedVMSwitch -eq $null) - { - throw [System.Management.Automation.ActionPreferenceStopException]'No switch can be found by given criteria.' - } - - return $script:mockedVMSwitch - } - - <# - Mocks New-VMSwitch and will assign a mocked switch to $script:mockedVMSwitch. This returns $script:mockedVMSwitch - which is a variable that is created during most It statements to mock a VMSwitch - #> - Mock -CommandName New-VMSwitch -MockWith { - param - ( - [Parameter()] - [System.String] - $Name, - - [Parameter()] - [System.String[]] - $NetAdapterName, - - [Parameter()] - [System.String] - $MinimumBandwidthMode = 'NA', - - [Parameter()] - [System.Boolean] - $EnableEmbeddedTeaming, - - [Parameter()] - [System.Boolean] - $AllowManagementOS - ) - - $script:mockedVMSwitch = New-MockedVMSwitch -Name $Name -BandwidthReservationMode $MinimumBandwidthMode -AllowManagementOS $AllowManagementOS - #is SET is enabled mok a VMSwitchTeam - if ($EnableEmbeddedTeaming) - { - $script:mockedVMSwitchTeam = [PSCustomObject]@{ - Name = "TestSwitch" - Id = [Guid]::NewGuid() - TeamingMode = 'SwitchIndependent' - LoadBalancingAlgorithm = 'Dynamic' - } - } - return $script:mockedVMSwitch - } - - Mock -CommandName Get-OSVersion -MockWith { - return @{ - Major = 10 - } - } - - <# - Mocks Remove-VMSwitch and will remove the variable $script:mockedVMSwitch which is - a variable that is created during most It statements to mock a VMSwitch - #> - Mock -CommandName Remove-VMSwitch -MockWith { - $script:mockedVMSwitch = $null - } - - <# - Mocks Get-VMSwitchTeam and will return a moked VMSwitchTeam - #> - Mock -CommandName Get-VMSwitchTeam -MockWith { - return $script:mockedVMSwitchTeam - } - - Mock -CommandName Set-VMSwitchTeam - - # Mocks Get-NetAdapter which returns a simplified network adapter - Mock -CommandName Get-NetAdapter -MockWith { - return @( - [PSCustomObject]@{ - Name = 'NIC1' - InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #1' - } - [PSCustomObject]@{ - Name = 'NIC2' - InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #2' - } - ) - } - - # 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 - } - - Context "A virtual switch with embedded teaming does not exist but should" { - $script:mockedVMSwitch = $null - - $testParams = @{ - Name = "TestSwitch" - Type = "External" - NetAdapterName = @("NIC1", "NIC2") - AllowManagementOS = $true - EnableEmbeddedTeaming = $true - BandwidthReservationMode = "NA" - Ensure = "Present" - } - - It "Should return absent in the get method" { - (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Absent" - } - - It "Should return false in the test method" { - Test-TargetResource @testParams | Should -Be $false - } - - It "Should run the set method without exceptions" { - Set-TargetResource @testParams - Assert-MockCalled -CommandName "New-VMSwitch" -Times 1 - } - } - - Context "A virtual switch with embedded teaming exists and should" { - $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() - $mockVMSwitch.Name = 'NewSwitch' - $mockVMSwitch.SwitchType = 'External' - $mockVMSwitch.AllowManagementOS = $true - $mockVMSwitch.EmbeddedTeamingEnabled = $true - $mockVMSwitch.Id = [Guid]::NewGuid() - $mockVMSwitch.NetAdapterInterfaceDescriptions = @( - 'Microsoft Network Adapter Multiplexor Driver #1', - 'Microsoft Network Adapter Multiplexor Driver #2' - ) - - Mock -CommandName Get-VMSwitch -MockWith { - return $mockVMSwitch - } -ParameterFilter { - $Name -eq 'NewSwitch' - } - - $testParams = @{ - Name = "NewSwitch" - Type = "External" - NetAdapterName = @("NIC1", "NIC2") - AllowManagementOS = $true - EnableEmbeddedTeaming = $true - Ensure = "Present" - } - - It "Should return present in the get method" { - (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" - } - - It "Should return true in the test method" { - Test-TargetResource @testParams | Should -Be $true - } - } - - Context "A virtual switch with embedded teaming exists but does not refer to the correct adapters" { - $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() - $mockVMSwitch.Name = 'NewSwitch' - $mockVMSwitch.SwitchType = 'External' - $mockVMSwitch.AllowManagementOS = $true - $mockVMSwitch.EmbeddedTeamingEnabled = $true - $mockVMSwitch.Id = [Guid]::NewGuid() - $mockVMSwitch.NetAdapterInterfaceDescriptions = @( - 'Wrong adapter', - 'Microsoft Network Adapter Multiplexor Driver #2' - ) - - Mock -CommandName Get-VMSwitch -MockWith { - return $mockVMSwitch - } -ParameterFilter { - $Name -eq 'NewSwitch' - } - - Mock -CommandName Get-NetAdapter -MockWith { - return @( - [PSCustomObject]@{ - Name = 'WrongNic' - InterfaceDescription = 'Wrong adapter' - } - [PSCustomObject]@{ - Name = 'NIC2' - InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #2' - } - ) - } - - $testParams = @{ - Name = "NewSwitch" - Type = "External" - NetAdapterName = @("NIC1", "NIC2") - AllowManagementOS = $true - EnableEmbeddedTeaming = $true - Ensure = "Present" - } - - It "Should return present in the get method" { - (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" - } - - It "Should return false in the test method" { - Test-TargetResource @testParams | Should -Be $false - } - - It "Should run the set method without exceptions" { - Set-TargetResource @testParams - Assert-MockCalled -CommandName "Remove-VMSwitch" -Times 1 - Assert-MockCalled -CommandName "New-VMSwitch" -Times 1 - } - } - - Context "A virtual switch with embedded teaming exists but does not use the correct LB algorithm" { - $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() - $mockVMSwitch.Name = 'NewSwitch' - $mockVMSwitch.SwitchType = 'External' - $mockVMSwitch.AllowManagementOS = $true - $mockVMSwitch.EmbeddedTeamingEnabled = $true - $mockVMSwitch.Id = [Guid]::NewGuid() - $mockVMSwitch.NetAdapterInterfaceDescriptions = @( - 'Microsoft Network Adapter Multiplexor Driver #1', - 'Microsoft Network Adapter Multiplexor Driver #2' - ) - - Mock -CommandName Get-VMSwitch -MockWith { - return $mockVMSwitch - } -ParameterFilter { - $Name -eq 'NewSwitch' - } - - $mockVMSwitchTeam = [Microsoft.HyperV.PowerShell.VMSwitchTeam]::CreateTypeInstance() - $mockVMSwitchTeam.Name = 'SwitchTeam' - $mockVMSwitchTeam.LoadBalancingAlgorithm = 'Dynamic' - $mockVMSwitchTeam.Id = [Guid]::NewGuid() - - Mock -CommandName Get-VMSwitchTeam -MockWith { - return $mockVMSwitchTeam - } - - Mock -CommandName Get-NetAdapter -MockWith { - return @( - [PSCustomObject]@{ - Name = 'NIC01' - InterfaceDescription = "Microsoft Network Adapter Multiplexor Driver #1" - } - [PSCustomObject]@{ - Name = 'NIC2' - InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #2' - } - ) - } - - $testParams = @{ - Name = "NewSwitch" - Type = "External" - NetAdapterName = @("NIC1", "NIC2") - AllowManagementOS = $true - EnableEmbeddedTeaming = $true - LoadBalancingAlgorithm = 'HyperVPort' - Ensure = "Present" - } - - It "Should return present in the get method" { - (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" - } - - It "Should return false in the test method" { - Test-TargetResource @testParams | Should -Be $false - } - - It "Should run the set method without exceptions" { - Set-TargetResource @testParams - Assert-MockCalled -CommandName "Remove-VMSwitch" -Times 1 - Assert-MockCalled -CommandName "New-VMSwitch" -Times 1 - } - } - - Context "A virtual switch without embedded teaming exists but should use embedded teaming" { - $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() - $mockVMSwitch.Name = 'NewSwitch' - $mockVMSwitch.SwitchType = 'External' - $mockVMSwitch.AllowManagementOS = $true - $mockVMSwitch.EmbeddedTeamingEnabled = $false - $mockVMSwitch.Id = [Guid]::NewGuid() - $mockVMSwitch.NetAdapterInterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #1' - - Mock -CommandName Get-VMSwitch -MockWith { - return $mockVMSwitch - } -ParameterFilter { - $Name -eq 'NewSwitch' - } - - $testParams = @{ - Name = "NewSwitch" - Type = "External" - NetAdapterName = @("NIC1", "NIC2") - AllowManagementOS = $true - EnableEmbeddedTeaming = $true - BandwidthReservationMode = "NA" - Ensure = "Present" - } - - It "Should return present in the get method" { - (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" - } - - It "Should return false in the test method" { - Test-TargetResource @testParams | Should -Be $false - } - - It "Should run the set method without exceptions" { - Set-TargetResource @testParams - Assert-MockCalled -CommandName "Remove-VMSwitch" -Times 1 - Assert-MockCalled -CommandName "New-VMSwitch" -Times 1 - } - } - - Context "A virtual switch with embedded teaming exists but shouldn't" { - $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() - $mockVMSwitch.Name = 'NewSwitch' - $mockVMSwitch.SwitchType = 'External' - $mockVMSwitch.AllowManagementOS = $true - $mockVMSwitch.EmbeddedTeamingEnabled = $true - $mockVMSwitch.Id = [Guid]::NewGuid() - $mockVMSwitch.NetAdapterInterfaceDescriptions = @( - 'Microsoft Network Adapter Multiplexor Driver #1', - 'Microsoft Network Adapter Multiplexor Driver #2' - ) - - Mock -CommandName Get-VMSwitch -MockWith { - return $mockVMSwitch - } -ParameterFilter { - $Name -eq 'NewSwitch' - } - - $testParams = @{ - Name = "NewSwitch" - Type = "Internal" - Ensure = "Absent" - } - - It "Should return present in the get method" { - (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" - } - - It "Should return false in the test method" { - Test-TargetResource @testParams | Should -Be $false - } - - It "Should run the set method without exceptions" { - Set-TargetResource @testParams - Assert-MockCalled -CommandName "Remove-VMSwitch" -Times 1 - } - } - - Context "A virtual switch with embedded teaming does not exist and shouldn't" { - $script:mockedVMSwitch = $null - - $testParams = @{ - Name = "TestSwitch" - Type = "Internal" - Ensure = "Absent" - } - - It "Should return absent in the get method" { - (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Absent" - } - - It "Should return true in the test method" { - Test-TargetResource @testParams | Should -Be $true - } - } - - Context "A server is not running Server 2016 and attempts to use embedded teaming" { - $script:mockedVMSwitch = $null - - $testParams = @{ - Name = "TestSwitch" - Type = "External" - NetAdapterName = @("NIC1", "NIC2") - AllowManagementOS = $true - EnableEmbeddedTeaming = $true - BandwidthReservationMode = "NA" - Ensure = "Present" - } - - Mock -CommandName Get-OSVersion -MockWith { - return [Version]::Parse('6.3.9600') - } - - It "Should return absent in the get method" { - (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Absent" - } - - It "Should throw an error in the test method" { - $errorMessage = $script:localizedData.SETServer2016Error - - {Test-TargetResource @testParams} | Should -Throw $errorMessage - } - - It "Should throw an error in the set method" { - $errorMessage = $script:localizedData.SETServer2016Error - - {Set-TargetResource @testParams} | Should -Throw $errorMessage - } - } - } - } -} -finally -{ - Invoke-TestCleanup -} +# $script:dscModuleName = 'HyperVDsc' +# $script:dscResourceName = 'DSC_VMSwitch' + +# function Invoke-TestSetup +# { +# try +# { +# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' +# } +# catch [System.IO.FileNotFoundException] +# { +# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' +# } + +# $script:testEnvironment = Initialize-TestEnvironment ` +# -DSCModuleName $script:dscModuleName ` +# -DSCResourceName $script:dscResourceName ` +# -ResourceType 'Mof' ` +# -TestType 'Unit' + +# # Import the stub functions. +# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +# } + +# function Invoke-TestCleanup +# { +# Restore-TestEnvironment -TestEnvironment $script:testEnvironment +# } + +# Invoke-TestSetup + +# try +# { +# InModuleScope $script:dscResourceName { +# # A helper function to mock a VMSwitch +# function New-MockedVMSwitch +# { +# param +# ( +# [Parameter(Mandatory = $true)] +# [System.String] +# $Name, + +# [Parameter(Mandatory = $true)] +# [ValidateSet('Default', 'Weight', 'Absolute', 'None', 'NA')] +# [System.String] +# $BandwidthReservationMode, + +# [Parameter()] +# [ValidateSet('Dynamic','HyperVPort')] +# [System.String] +# $LoadBalancingAlgorithm, + +# [Parameter()] +# [System.Boolean] +# $AllowManagementOS = $false +# ) + +# $mockedVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() +# $mockedVMSwitch.Name = $Name +# $mockedVMSwitch.SwitchType = 'External' +# $mockedVMSwitch.AllowManagementOS = $AllowManagementOS +# $mockedVMSwitch.NetAdapterInterfaceDescriptions = 'Microsoft Network Adapter Multiplexor Driver' + +# if ($BandwidthReservationMode -ne 'NA') +# { +# $mockedVMSwitch.BandwidthReservationMode = $BandwidthReservationMode +# } + +# if ($PSBoundParameters.ContainsKey('LoadBalancingAlgorithm')) +# { +# $mockedVMSwitch.LoadBalancingAlgorithm = $LoadBalancingAlgorithm +# } + +# return $mockedVMSwitch +# } + +# Describe "DSC_VMSwitch" { +# <# +# Mocks Get-VMSwitch and will return $script:mockedVMSwitch which is +# a variable that is created during most It statements to mock a VMSwitch +# #> +# Mock -CommandName Get-VMSwitch -MockWith { +# if ($ErrorAction -eq 'Stop' -and $script:mockedVMSwitch -eq $null) +# { +# throw [System.Management.Automation.ActionPreferenceStopException]'No switch can be found by given criteria.' +# } + +# return $script:mockedVMSwitch +# } + +# <# +# Mocks New-VMSwitch and will assign a mocked switch to $script:mockedVMSwitch. This returns $script:mockedVMSwitch +# which is a variable that is created during most It statements to mock a VMSwitch +# #> +# Mock -CommandName New-VMSwitch -MockWith { +# param +# ( +# [Parameter()] +# [System.String] +# $Name, + +# [Parameter()] +# [System.String[]] +# $NetAdapterName, + +# [Parameter()] +# [System.String] +# $MinimumBandwidthMode = 'NA', + +# [Parameter()] +# [System.Boolean] +# $EnableEmbeddedTeaming, + +# [Parameter()] +# [System.Boolean] +# $AllowManagementOS +# ) + +# $script:mockedVMSwitch = New-MockedVMSwitch -Name $Name -BandwidthReservationMode $MinimumBandwidthMode -AllowManagementOS $AllowManagementOS +# #is SET is enabled mok a VMSwitchTeam +# if ($EnableEmbeddedTeaming) +# { +# $script:mockedVMSwitchTeam = [PSCustomObject]@{ +# Name = "TestSwitch" +# Id = [Guid]::NewGuid() +# TeamingMode = 'SwitchIndependent' +# LoadBalancingAlgorithm = 'Dynamic' +# } +# } +# return $script:mockedVMSwitch +# } + +# Mock -CommandName Get-OSVersion -MockWith { +# return @{ +# Major = 10 +# } +# } + +# <# +# Mocks Remove-VMSwitch and will remove the variable $script:mockedVMSwitch which is +# a variable that is created during most It statements to mock a VMSwitch +# #> +# Mock -CommandName Remove-VMSwitch -MockWith { +# $script:mockedVMSwitch = $null +# } + +# <# +# Mocks Get-VMSwitchTeam and will return a moked VMSwitchTeam +# #> +# Mock -CommandName Get-VMSwitchTeam -MockWith { +# return $script:mockedVMSwitchTeam +# } + +# Mock -CommandName Set-VMSwitchTeam + +# # Mocks Get-NetAdapter which returns a simplified network adapter +# Mock -CommandName Get-NetAdapter -MockWith { +# return @( +# [PSCustomObject]@{ +# Name = 'NIC1' +# InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #1' +# } +# [PSCustomObject]@{ +# Name = 'NIC2' +# InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #2' +# } +# ) +# } + +# # 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 +# } + +# Context "A virtual switch with embedded teaming does not exist but should" { +# $script:mockedVMSwitch = $null + +# $testParams = @{ +# Name = "TestSwitch" +# Type = "External" +# NetAdapterName = @("NIC1", "NIC2") +# AllowManagementOS = $true +# EnableEmbeddedTeaming = $true +# BandwidthReservationMode = "NA" +# Ensure = "Present" +# } + +# It "Should return absent in the get method" { +# (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Absent" +# } + +# It "Should return false in the test method" { +# Test-TargetResource @testParams | Should -Be $false +# } + +# It "Should run the set method without exceptions" { +# Set-TargetResource @testParams +# Assert-MockCalled -CommandName "New-VMSwitch" -Times 1 +# } +# } + +# Context "A virtual switch with embedded teaming exists and should" { +# $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() +# $mockVMSwitch.Name = 'NewSwitch' +# $mockVMSwitch.SwitchType = 'External' +# $mockVMSwitch.AllowManagementOS = $true +# $mockVMSwitch.EmbeddedTeamingEnabled = $true +# $mockVMSwitch.Id = [Guid]::NewGuid() +# $mockVMSwitch.NetAdapterInterfaceDescriptions = @( +# 'Microsoft Network Adapter Multiplexor Driver #1', +# 'Microsoft Network Adapter Multiplexor Driver #2' +# ) + +# Mock -CommandName Get-VMSwitch -MockWith { +# return $mockVMSwitch +# } -ParameterFilter { +# $Name -eq 'NewSwitch' +# } + +# $testParams = @{ +# Name = "NewSwitch" +# Type = "External" +# NetAdapterName = @("NIC1", "NIC2") +# AllowManagementOS = $true +# EnableEmbeddedTeaming = $true +# Ensure = "Present" +# } + +# It "Should return present in the get method" { +# (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" +# } + +# It "Should return true in the test method" { +# Test-TargetResource @testParams | Should -Be $true +# } +# } + +# Context "A virtual switch with embedded teaming exists but does not refer to the correct adapters" { +# $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() +# $mockVMSwitch.Name = 'NewSwitch' +# $mockVMSwitch.SwitchType = 'External' +# $mockVMSwitch.AllowManagementOS = $true +# $mockVMSwitch.EmbeddedTeamingEnabled = $true +# $mockVMSwitch.Id = [Guid]::NewGuid() +# $mockVMSwitch.NetAdapterInterfaceDescriptions = @( +# 'Wrong adapter', +# 'Microsoft Network Adapter Multiplexor Driver #2' +# ) + +# Mock -CommandName Get-VMSwitch -MockWith { +# return $mockVMSwitch +# } -ParameterFilter { +# $Name -eq 'NewSwitch' +# } + +# Mock -CommandName Get-NetAdapter -MockWith { +# return @( +# [PSCustomObject]@{ +# Name = 'WrongNic' +# InterfaceDescription = 'Wrong adapter' +# } +# [PSCustomObject]@{ +# Name = 'NIC2' +# InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #2' +# } +# ) +# } + +# $testParams = @{ +# Name = "NewSwitch" +# Type = "External" +# NetAdapterName = @("NIC1", "NIC2") +# AllowManagementOS = $true +# EnableEmbeddedTeaming = $true +# Ensure = "Present" +# } + +# It "Should return present in the get method" { +# (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" +# } + +# It "Should return false in the test method" { +# Test-TargetResource @testParams | Should -Be $false +# } + +# It "Should run the set method without exceptions" { +# Set-TargetResource @testParams +# Assert-MockCalled -CommandName "Remove-VMSwitch" -Times 1 +# Assert-MockCalled -CommandName "New-VMSwitch" -Times 1 +# } +# } + +# Context "A virtual switch with embedded teaming exists but does not use the correct LB algorithm" { +# $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() +# $mockVMSwitch.Name = 'NewSwitch' +# $mockVMSwitch.SwitchType = 'External' +# $mockVMSwitch.AllowManagementOS = $true +# $mockVMSwitch.EmbeddedTeamingEnabled = $true +# $mockVMSwitch.Id = [Guid]::NewGuid() +# $mockVMSwitch.NetAdapterInterfaceDescriptions = @( +# 'Microsoft Network Adapter Multiplexor Driver #1', +# 'Microsoft Network Adapter Multiplexor Driver #2' +# ) + +# Mock -CommandName Get-VMSwitch -MockWith { +# return $mockVMSwitch +# } -ParameterFilter { +# $Name -eq 'NewSwitch' +# } + +# $mockVMSwitchTeam = [Microsoft.HyperV.PowerShell.VMSwitchTeam]::CreateTypeInstance() +# $mockVMSwitchTeam.Name = 'SwitchTeam' +# $mockVMSwitchTeam.LoadBalancingAlgorithm = 'Dynamic' +# $mockVMSwitchTeam.Id = [Guid]::NewGuid() + +# Mock -CommandName Get-VMSwitchTeam -MockWith { +# return $mockVMSwitchTeam +# } + +# Mock -CommandName Get-NetAdapter -MockWith { +# return @( +# [PSCustomObject]@{ +# Name = 'NIC01' +# InterfaceDescription = "Microsoft Network Adapter Multiplexor Driver #1" +# } +# [PSCustomObject]@{ +# Name = 'NIC2' +# InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #2' +# } +# ) +# } + +# $testParams = @{ +# Name = "NewSwitch" +# Type = "External" +# NetAdapterName = @("NIC1", "NIC2") +# AllowManagementOS = $true +# EnableEmbeddedTeaming = $true +# LoadBalancingAlgorithm = 'HyperVPort' +# Ensure = "Present" +# } + +# It "Should return present in the get method" { +# (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" +# } + +# It "Should return false in the test method" { +# Test-TargetResource @testParams | Should -Be $false +# } + +# It "Should run the set method without exceptions" { +# Set-TargetResource @testParams +# Assert-MockCalled -CommandName "Remove-VMSwitch" -Times 1 +# Assert-MockCalled -CommandName "New-VMSwitch" -Times 1 +# } +# } + +# Context "A virtual switch without embedded teaming exists but should use embedded teaming" { +# $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() +# $mockVMSwitch.Name = 'NewSwitch' +# $mockVMSwitch.SwitchType = 'External' +# $mockVMSwitch.AllowManagementOS = $true +# $mockVMSwitch.EmbeddedTeamingEnabled = $false +# $mockVMSwitch.Id = [Guid]::NewGuid() +# $mockVMSwitch.NetAdapterInterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #1' + +# Mock -CommandName Get-VMSwitch -MockWith { +# return $mockVMSwitch +# } -ParameterFilter { +# $Name -eq 'NewSwitch' +# } + +# $testParams = @{ +# Name = "NewSwitch" +# Type = "External" +# NetAdapterName = @("NIC1", "NIC2") +# AllowManagementOS = $true +# EnableEmbeddedTeaming = $true +# BandwidthReservationMode = "NA" +# Ensure = "Present" +# } + +# It "Should return present in the get method" { +# (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" +# } + +# It "Should return false in the test method" { +# Test-TargetResource @testParams | Should -Be $false +# } + +# It "Should run the set method without exceptions" { +# Set-TargetResource @testParams +# Assert-MockCalled -CommandName "Remove-VMSwitch" -Times 1 +# Assert-MockCalled -CommandName "New-VMSwitch" -Times 1 +# } +# } + +# Context "A virtual switch with embedded teaming exists but shouldn't" { +# $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() +# $mockVMSwitch.Name = 'NewSwitch' +# $mockVMSwitch.SwitchType = 'External' +# $mockVMSwitch.AllowManagementOS = $true +# $mockVMSwitch.EmbeddedTeamingEnabled = $true +# $mockVMSwitch.Id = [Guid]::NewGuid() +# $mockVMSwitch.NetAdapterInterfaceDescriptions = @( +# 'Microsoft Network Adapter Multiplexor Driver #1', +# 'Microsoft Network Adapter Multiplexor Driver #2' +# ) + +# Mock -CommandName Get-VMSwitch -MockWith { +# return $mockVMSwitch +# } -ParameterFilter { +# $Name -eq 'NewSwitch' +# } + +# $testParams = @{ +# Name = "NewSwitch" +# Type = "Internal" +# Ensure = "Absent" +# } + +# It "Should return present in the get method" { +# (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" +# } + +# It "Should return false in the test method" { +# Test-TargetResource @testParams | Should -Be $false +# } + +# It "Should run the set method without exceptions" { +# Set-TargetResource @testParams +# Assert-MockCalled -CommandName "Remove-VMSwitch" -Times 1 +# } +# } + +# Context "A virtual switch with embedded teaming does not exist and shouldn't" { +# $script:mockedVMSwitch = $null + +# $testParams = @{ +# Name = "TestSwitch" +# Type = "Internal" +# Ensure = "Absent" +# } + +# It "Should return absent in the get method" { +# (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Absent" +# } + +# It "Should return true in the test method" { +# Test-TargetResource @testParams | Should -Be $true +# } +# } + +# Context "A server is not running Server 2016 and attempts to use embedded teaming" { +# $script:mockedVMSwitch = $null + +# $testParams = @{ +# Name = "TestSwitch" +# Type = "External" +# NetAdapterName = @("NIC1", "NIC2") +# AllowManagementOS = $true +# EnableEmbeddedTeaming = $true +# BandwidthReservationMode = "NA" +# Ensure = "Present" +# } + +# Mock -CommandName Get-OSVersion -MockWith { +# return [Version]::Parse('6.3.9600') +# } + +# It "Should return absent in the get method" { +# (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Absent" +# } + +# It "Should throw an error in the test method" { +# $errorMessage = $script:localizedData.SETServer2016Error + +# {Test-TargetResource @testParams} | Should -Throw $errorMessage +# } + +# It "Should throw an error in the set method" { +# $errorMessage = $script:localizedData.SETServer2016Error + +# {Set-TargetResource @testParams} | Should -Throw $errorMessage +# } +# } +# } +# } +# } +# finally +# { +# Invoke-TestCleanup +# } diff --git a/tests/Unit/DSC_VMSwitch_Id.Tests.ps1 b/tests/Unit/DSC_VMSwitch_Id.Tests.ps1 index f63b968..e302833 100644 --- a/tests/Unit/DSC_VMSwitch_Id.Tests.ps1 +++ b/tests/Unit/DSC_VMSwitch_Id.Tests.ps1 @@ -1,376 +1,376 @@ -$script:dscModuleName = 'HyperVDsc' -$script:dscResourceName = 'DSC_VMSwitch' - -function Invoke-TestSetup -{ - try - { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' - } - catch [System.IO.FileNotFoundException] - { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' - } - - $script:testEnvironment = Initialize-TestEnvironment ` - -DSCModuleName $script:dscModuleName ` - -DSCResourceName $script:dscResourceName ` - -ResourceType 'Mof' ` - -TestType 'Unit' - - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -} - -function Invoke-TestCleanup -{ - Restore-TestEnvironment -TestEnvironment $script:testEnvironment -} - -Invoke-TestSetup - -try -{ - InModuleScope $script:dscResourceName { - # A helper function to mock a VMSwitch - function New-MockedVMSwitch - { - param ( - [Parameter(Mandatory = $true)] - [System.String] - $Name, - - [Parameter()] - [ValidateNotNullOrEmpty()] - [Guid] - $Id - ) - - $mockedVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() - $mockedVMSwitch.Name = $Name - $mockedVMSwitch.SwitchType = 'External' - $mockedVMSwitch.AllowManagementOS = $true - $mockedVMSwitch.EmbeddedTeamingEnabled = $true - $mockedVMSwitch.BandwidthReservationMode = 'Default' - $mockedVMSwitch.NetAdapterInterfaceDescriptions = @( - 'Microsoft Network Adapter Multiplexor Driver #1', - 'Microsoft Network Adapter Multiplexor Driver #2' - ) - - if ($PSBoundParameters.ContainsKey('Id')) - { - $mockedVMSwitch.Id = $Id - } - else - { - $mockedVMSwitch.Id = New-Guid - } - - return $mockedVMSwitch - } - - # 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 -CommandName Get-VMSwitch -MockWith { - return $script:MockedVMSwitch - } - - Mock -CommandName Get-NetAdapter -MockWith { - return @( - [PSCustomObject]@{ - Name = 'NIC1' - InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #1' - } - [PSCustomObject]@{ - Name = 'NIC2' - InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #2' - } - ) - } - - Mock -CommandName Get-VMSwitchTeam -MockWith { - return [PSCustomObject]@{ - Name = 'TestTeam' - Id = New-Guid - NetAdapterInterfaceDescription = @("Microsoft Network Adapter Multiplexor Driver #1", "Microsoft Network Adapter Multiplexor Driver #2") - TeamingMode = 'SwitchIndependent' - LoadBalancingAlgorithm = 'HyperVPort' - } - } - - Mock -CommandName Remove-VMSwitch -MockWith { - $script:mockedVMSwitch = $null - } - - Mock -CommandName New-VMSwitch -MockWith { - param - ( - [Parameter()] - [System.String] - $Name, - - [Parameter()] - [System.String[]] - $NetAdapterName, - - [Parameter()] - [System.String] - $MinimumBandwidthMode, - - [Parameter()] - [System.Boolean] - $AllowManagementOS, - - [Parameter()] - [System.String] - $SwitchType, - - [Parameter()] - [System.Boolean] - $EnableEmbeddedTeaming, - - [Parameter()] - [Guid] - $Id - ) - - if ($PSBoundParameters.ContainsKey('Id')) - { - $script:MockedVMSwitch = New-MockedVMSwitch -Name $Name -Id $id - } - else - { - $script:MockedVMSwitch = New-MockedVMSwitch -Name $Name - } - } - - Mock -CommandName Get-OSVersion -MockWith { - [PSCustomObject]@{ - Major = 10 - Minor = 0 - Build = 14393 - Revision = 0 - MajorRevision = 0 - MinorRevision = 0 - } - } - - Describe 'DSC_VMSwitch\Get-TargetResource' -Tag 'Get' { - - Context 'When the system is in the desired state (VMSwitch has the desired Id)' { - $script:MockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' - - It 'Should return "present"' { - (Get-TargetResource -Name 'TestSwitch' -Type 'External').Ensure | Should -Be 'Present' - Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 - Assert-MockCalled -CommandName "Get-VMSwitchTeam" -Times 1 - } - } - - Context 'When the system is not in the desired state (VMSwitch has not the desired Id)' { - - $script:mockedVMSwitch = $null - - It 'Should return "absent"' { - (Get-TargetResource -Name 'TestSwitch' -Type 'External').Ensure | Should -Be 'Absent' - Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 - Assert-MockCalled -CommandName "Get-VMSwitchTeam" -Times 0 - } - } - } - - Describe 'DSC_VMSwitch\Set-TargetResource' -Tag 'Set' { - - Context 'When the system is in the desired state (VMSwitch has the desired Id)' { - $desiredVMSwitchID = New-Guid - - $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' -Id $desiredVMSwitchID - - $testParams = @{ - Name = 'TestSwitch' - Type = 'External' - NetAdapterName = @('NIC1', 'NIC2') - AllowManagementOS = $true - EnableEmbeddedTeaming = $true - Ensure = 'Present' - Id = $desiredVMSwitchID - } - - It 'Should run without without exceptions' { - {Set-TargetResource @testParams} | Should -Not -throw - Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 - Assert-MockCalled -CommandName 'Get-NetAdapter' -Times 1 - } - } - - Context 'When the system is not in the desired state (VMSwitch has not the desired Id)' { - - $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' - - $testParams = @{ - Name = 'TestSwitch' - Type = 'External' - NetAdapterName = @('NIC1', 'NIC2') - AllowManagementOS = $true - EnableEmbeddedTeaming = $true - Ensure = 'Present' - Id = New-Guid - } - - It 'Should run without exception while re-creating the VMSwitch' { - {Set-TargetResource @testParams} | Should -Not -throw - Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 - Assert-MockCalled -CommandName 'Get-NetAdapter' -Times 1 - Assert-MockCalled -CommandName 'Remove-VMSwitch' -Times 1 - Assert-MockCalled -CommandName 'New-VMSwitch' -Times 1 - } - } - - Context 'When the specified value for Id parameter is not a GUID' { - - $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' - - $testParams = @{ - Name = 'TestSwitch' - Type = 'External' - NetAdapterName = @('NIC1', 'NIC2') - AllowManagementOS = $true - EnableEmbeddedTeaming = $true - Ensure = 'Present' - Id = '123' - } - - It 'Should throw "The VMSwitch Id must be in GUID format!"' { - {Set-TargetResource @testParams} | Should -Throw 'The VMSwitch Id must be in GUID format!' - } - } - - Context 'When the system is not running Server 2016' { - - $desiredVMSwitchID = New-Guid - - $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' -Id $desiredVMSwitchID - - $testParams = @{ - Name = 'TestSwitch' - Type = 'External' - NetAdapterName = 'NIC1' - AllowManagementOS = $true - EnableEmbeddedTeaming = $false - Ensure = 'Present' - Id = $desiredVMSwitchID - } - - Mock -CommandName Get-OSVersion -MockWith { - return [Version]::Parse('6.3.9600') - } - - $errorMessage = $script:localizedData.VMSwitchIDServer2016Error - - It 'Should throw "VMSwitchIDServer2016Error"' { - {Set-TargetResource @testParams} | Should -Throw $errorMessage - } - } - } - - Describe 'DSC_VMSwitch\Test-TargetResource' -Tag 'Test' { - Context 'When the system is in the desired state (VMSwitch has the desired Id)' { - - $desiredVMSwitchID = New-Guid - - $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' -Id $desiredVMSwitchID - - $testParams = @{ - Name = 'TestSwitch' - Type = 'External' - NetAdapterName = @('NIC1', 'NIC2') - AllowManagementOS = $true - EnableEmbeddedTeaming = $true - Ensure = 'Present' - Id = $desiredVMSwitchID - } - - It 'Should return $true' { - {Test-TargetResource @testParams} | Should -Not -throw - Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 - Assert-MockCalled -CommandName 'Get-NetAdapter' -Times 1 - } - } - - Context 'When the system is not in the desired state (VMSwitch has not the desired Id)' { - - $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' - - $testParams = @{ - Name = 'TestSwitch' - Type = 'External' - NetAdapterName = @('NIC1', 'NIC2') - AllowManagementOS = $true - EnableEmbeddedTeaming = $true - Ensure = 'Present' - Id = New-Guid - } - - It 'Should return $false' { - {Test-TargetResource @testParams} | Should -Not -throw - Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 - Assert-MockCalled -CommandName 'Get-NetAdapter' -Times 1 - } - } - - Context 'When the specified value for Id parameter is not a GUID' { - - $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' - - $testParams = @{ - Name = 'TestSwitch' - Type = 'External' - NetAdapterName = @('NIC1', 'NIC2') - AllowManagementOS = $true - EnableEmbeddedTeaming = $true - Ensure = 'Present' - Id = '123' - } - - It 'Should throw "The VMSwitch Id must be in GUID format!"' { - {Test-TargetResource @testParams} | Should -Throw 'The VMSwitch Id must be in GUID format!' - } - } - - Context 'When the system is not running Server 2016' { - - $desiredVMSwitchID = New-Guid - - $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' -Id $desiredVMSwitchID - - $testParams = @{ - Name = 'TestSwitch' - Type = 'External' - NetAdapterName = 'NIC1' - AllowManagementOS = $true - EnableEmbeddedTeaming = $false - Ensure = 'Present' - Id = $desiredVMSwitchID - } - - Mock -CommandName Get-OSVersion -MockWith { - return [Version]::Parse('6.3.9600') - } - - $errorMessage = $script:localizedData.VMSwitchIDServer2016Error - - It 'Should throw "VMSwitchIDServer2016Error"' { - {Test-TargetResource @testParams} | Should -Throw $errorMessage - } - } - - } - } -} -finally -{ - Invoke-TestCleanup -} +# $script:dscModuleName = 'HyperVDsc' +# $script:dscResourceName = 'DSC_VMSwitch' + +# function Invoke-TestSetup +# { +# try +# { +# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' +# } +# catch [System.IO.FileNotFoundException] +# { +# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' +# } + +# $script:testEnvironment = Initialize-TestEnvironment ` +# -DSCModuleName $script:dscModuleName ` +# -DSCResourceName $script:dscResourceName ` +# -ResourceType 'Mof' ` +# -TestType 'Unit' + +# # Import the stub functions. +# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +# } + +# function Invoke-TestCleanup +# { +# Restore-TestEnvironment -TestEnvironment $script:testEnvironment +# } + +# Invoke-TestSetup + +# try +# { +# InModuleScope $script:dscResourceName { +# # A helper function to mock a VMSwitch +# function New-MockedVMSwitch +# { +# param ( +# [Parameter(Mandatory = $true)] +# [System.String] +# $Name, + +# [Parameter()] +# [ValidateNotNullOrEmpty()] +# [Guid] +# $Id +# ) + +# $mockedVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() +# $mockedVMSwitch.Name = $Name +# $mockedVMSwitch.SwitchType = 'External' +# $mockedVMSwitch.AllowManagementOS = $true +# $mockedVMSwitch.EmbeddedTeamingEnabled = $true +# $mockedVMSwitch.BandwidthReservationMode = 'Default' +# $mockedVMSwitch.NetAdapterInterfaceDescriptions = @( +# 'Microsoft Network Adapter Multiplexor Driver #1', +# 'Microsoft Network Adapter Multiplexor Driver #2' +# ) + +# if ($PSBoundParameters.ContainsKey('Id')) +# { +# $mockedVMSwitch.Id = $Id +# } +# else +# { +# $mockedVMSwitch.Id = New-Guid +# } + +# return $mockedVMSwitch +# } + +# # 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 -CommandName Get-VMSwitch -MockWith { +# return $script:MockedVMSwitch +# } + +# Mock -CommandName Get-NetAdapter -MockWith { +# return @( +# [PSCustomObject]@{ +# Name = 'NIC1' +# InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #1' +# } +# [PSCustomObject]@{ +# Name = 'NIC2' +# InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #2' +# } +# ) +# } + +# Mock -CommandName Get-VMSwitchTeam -MockWith { +# return [PSCustomObject]@{ +# Name = 'TestTeam' +# Id = New-Guid +# NetAdapterInterfaceDescription = @("Microsoft Network Adapter Multiplexor Driver #1", "Microsoft Network Adapter Multiplexor Driver #2") +# TeamingMode = 'SwitchIndependent' +# LoadBalancingAlgorithm = 'HyperVPort' +# } +# } + +# Mock -CommandName Remove-VMSwitch -MockWith { +# $script:mockedVMSwitch = $null +# } + +# Mock -CommandName New-VMSwitch -MockWith { +# param +# ( +# [Parameter()] +# [System.String] +# $Name, + +# [Parameter()] +# [System.String[]] +# $NetAdapterName, + +# [Parameter()] +# [System.String] +# $MinimumBandwidthMode, + +# [Parameter()] +# [System.Boolean] +# $AllowManagementOS, + +# [Parameter()] +# [System.String] +# $SwitchType, + +# [Parameter()] +# [System.Boolean] +# $EnableEmbeddedTeaming, + +# [Parameter()] +# [Guid] +# $Id +# ) + +# if ($PSBoundParameters.ContainsKey('Id')) +# { +# $script:MockedVMSwitch = New-MockedVMSwitch -Name $Name -Id $id +# } +# else +# { +# $script:MockedVMSwitch = New-MockedVMSwitch -Name $Name +# } +# } + +# Mock -CommandName Get-OSVersion -MockWith { +# [PSCustomObject]@{ +# Major = 10 +# Minor = 0 +# Build = 14393 +# Revision = 0 +# MajorRevision = 0 +# MinorRevision = 0 +# } +# } + +# Describe 'DSC_VMSwitch\Get-TargetResource' -Tag 'Get' { + +# Context 'When the system is in the desired state (VMSwitch has the desired Id)' { +# $script:MockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' + +# It 'Should return "present"' { +# (Get-TargetResource -Name 'TestSwitch' -Type 'External').Ensure | Should -Be 'Present' +# Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 +# Assert-MockCalled -CommandName "Get-VMSwitchTeam" -Times 1 +# } +# } + +# Context 'When the system is not in the desired state (VMSwitch has not the desired Id)' { + +# $script:mockedVMSwitch = $null + +# It 'Should return "absent"' { +# (Get-TargetResource -Name 'TestSwitch' -Type 'External').Ensure | Should -Be 'Absent' +# Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 +# Assert-MockCalled -CommandName "Get-VMSwitchTeam" -Times 0 +# } +# } +# } + +# Describe 'DSC_VMSwitch\Set-TargetResource' -Tag 'Set' { + +# Context 'When the system is in the desired state (VMSwitch has the desired Id)' { +# $desiredVMSwitchID = New-Guid + +# $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' -Id $desiredVMSwitchID + +# $testParams = @{ +# Name = 'TestSwitch' +# Type = 'External' +# NetAdapterName = @('NIC1', 'NIC2') +# AllowManagementOS = $true +# EnableEmbeddedTeaming = $true +# Ensure = 'Present' +# Id = $desiredVMSwitchID +# } + +# It 'Should run without without exceptions' { +# {Set-TargetResource @testParams} | Should -Not -throw +# Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 +# Assert-MockCalled -CommandName 'Get-NetAdapter' -Times 1 +# } +# } + +# Context 'When the system is not in the desired state (VMSwitch has not the desired Id)' { + +# $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' + +# $testParams = @{ +# Name = 'TestSwitch' +# Type = 'External' +# NetAdapterName = @('NIC1', 'NIC2') +# AllowManagementOS = $true +# EnableEmbeddedTeaming = $true +# Ensure = 'Present' +# Id = New-Guid +# } + +# It 'Should run without exception while re-creating the VMSwitch' { +# {Set-TargetResource @testParams} | Should -Not -throw +# Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 +# Assert-MockCalled -CommandName 'Get-NetAdapter' -Times 1 +# Assert-MockCalled -CommandName 'Remove-VMSwitch' -Times 1 +# Assert-MockCalled -CommandName 'New-VMSwitch' -Times 1 +# } +# } + +# Context 'When the specified value for Id parameter is not a GUID' { + +# $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' + +# $testParams = @{ +# Name = 'TestSwitch' +# Type = 'External' +# NetAdapterName = @('NIC1', 'NIC2') +# AllowManagementOS = $true +# EnableEmbeddedTeaming = $true +# Ensure = 'Present' +# Id = '123' +# } + +# It 'Should throw "The VMSwitch Id must be in GUID format!"' { +# {Set-TargetResource @testParams} | Should -Throw 'The VMSwitch Id must be in GUID format!' +# } +# } + +# Context 'When the system is not running Server 2016' { + +# $desiredVMSwitchID = New-Guid + +# $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' -Id $desiredVMSwitchID + +# $testParams = @{ +# Name = 'TestSwitch' +# Type = 'External' +# NetAdapterName = 'NIC1' +# AllowManagementOS = $true +# EnableEmbeddedTeaming = $false +# Ensure = 'Present' +# Id = $desiredVMSwitchID +# } + +# Mock -CommandName Get-OSVersion -MockWith { +# return [Version]::Parse('6.3.9600') +# } + +# $errorMessage = $script:localizedData.VMSwitchIDServer2016Error + +# It 'Should throw "VMSwitchIDServer2016Error"' { +# {Set-TargetResource @testParams} | Should -Throw $errorMessage +# } +# } +# } + +# Describe 'DSC_VMSwitch\Test-TargetResource' -Tag 'Test' { +# Context 'When the system is in the desired state (VMSwitch has the desired Id)' { + +# $desiredVMSwitchID = New-Guid + +# $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' -Id $desiredVMSwitchID + +# $testParams = @{ +# Name = 'TestSwitch' +# Type = 'External' +# NetAdapterName = @('NIC1', 'NIC2') +# AllowManagementOS = $true +# EnableEmbeddedTeaming = $true +# Ensure = 'Present' +# Id = $desiredVMSwitchID +# } + +# It 'Should return $true' { +# {Test-TargetResource @testParams} | Should -Not -throw +# Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 +# Assert-MockCalled -CommandName 'Get-NetAdapter' -Times 1 +# } +# } + +# Context 'When the system is not in the desired state (VMSwitch has not the desired Id)' { + +# $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' + +# $testParams = @{ +# Name = 'TestSwitch' +# Type = 'External' +# NetAdapterName = @('NIC1', 'NIC2') +# AllowManagementOS = $true +# EnableEmbeddedTeaming = $true +# Ensure = 'Present' +# Id = New-Guid +# } + +# It 'Should return $false' { +# {Test-TargetResource @testParams} | Should -Not -throw +# Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 +# Assert-MockCalled -CommandName 'Get-NetAdapter' -Times 1 +# } +# } + +# Context 'When the specified value for Id parameter is not a GUID' { + +# $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' + +# $testParams = @{ +# Name = 'TestSwitch' +# Type = 'External' +# NetAdapterName = @('NIC1', 'NIC2') +# AllowManagementOS = $true +# EnableEmbeddedTeaming = $true +# Ensure = 'Present' +# Id = '123' +# } + +# It 'Should throw "The VMSwitch Id must be in GUID format!"' { +# {Test-TargetResource @testParams} | Should -Throw 'The VMSwitch Id must be in GUID format!' +# } +# } + +# Context 'When the system is not running Server 2016' { + +# $desiredVMSwitchID = New-Guid + +# $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' -Id $desiredVMSwitchID + +# $testParams = @{ +# Name = 'TestSwitch' +# Type = 'External' +# NetAdapterName = 'NIC1' +# AllowManagementOS = $true +# EnableEmbeddedTeaming = $false +# Ensure = 'Present' +# Id = $desiredVMSwitchID +# } + +# Mock -CommandName Get-OSVersion -MockWith { +# return [Version]::Parse('6.3.9600') +# } + +# $errorMessage = $script:localizedData.VMSwitchIDServer2016Error + +# It 'Should throw "VMSwitchIDServer2016Error"' { +# {Test-TargetResource @testParams} | Should -Throw $errorMessage +# } +# } + +# } +# } +# } +# finally +# { +# Invoke-TestCleanup +# } diff --git a/tests/Unit/DSC_VhdFileDirectory.Tests.ps1 b/tests/Unit/DSC_VhdFileDirectory.Tests.ps1 index 41a9a66..160f989 100644 --- a/tests/Unit/DSC_VhdFileDirectory.Tests.ps1 +++ b/tests/Unit/DSC_VhdFileDirectory.Tests.ps1 @@ -1,531 +1,531 @@ -$script:dscModuleName = 'HyperVDsc' -$script:dscResourceName = 'DSC_VhdFileDirectory' - -function Invoke-TestSetup -{ - try - { - Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' - } - catch [System.IO.FileNotFoundException] - { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' - } - - $script:testEnvironment = Initialize-TestEnvironment ` - -DSCModuleName $script:dscModuleName ` - -DSCResourceName $script:dscResourceName ` - -ResourceType 'Mof' ` - -TestType 'Unit' - - # Import the stub functions. - Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -} - -function Invoke-TestCleanup -{ - Restore-TestEnvironment -TestEnvironment $script:testEnvironment -} - -Invoke-TestSetup - -try -{ - InModuleScope $script:dscResourceName { - - #region Functions, Variables and Mocks - function Get-FreeDriveLetter - { - [CmdletBinding()] - param() - - $upperCaseChars = 67..90 | ForEach-Object { [char]$_ } - $driveLettersInUse = Get-PsDrive | Where-Object -FilterScript { - $upperCaseChars -contains $_.name - } | Select-Object -ExpandProperty Name - - foreach ($char in $upperCaseChars) - { - if ($driveLettersInUse -notcontains $char) - { - Write-Verbose "Selecting $char to use as VhdDriveLetter" - - return $char - break - } - } -} - -function New-TestDriveLayout -{ - [CmdletBinding(SupportsShouldProcess, ConfirmImpact = "Medium")] - param( - [Parameter()] - [System.String] - $DriveLetter - ) - - # Source file structure - New-item -Path TestDrive:\VhdExists.vhdx - 'TestFile1' | Out-File TestDrive:\FileExists.txt - 'TestFile2' | Out-File TestDrive:\FileExists2.txt - 'TestFile3' | Out-File TestDrive:\FileExists3.txt - New-Item -Path TestDrive:\SourceDirectoryExists -ItemType Directory - New-Item -Path TestDrive:\SourceDirectoryExists2 -ItemType Directory - 'Some Text' | Out-File TestDrive:\SourceDirectoryExists\File1.txt - 'Some More Text' | Out-File TestDrive:\SourceDirectoryExists2\File2.txt - - # VhdRoot structure - New-Item -Path TestDrive:\MockVhdRoot -ItemType Directory - New-Item -Path TestDrive:\MockVhdRoot\DestinationDirectoryExists -ItemType Directory - Copy-Item -Path TestDrive:\FileExists.txt -Destination TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileExists.txt - Copy-Item -Path TestDrive:\FileExists2.txt -Destination TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileExists2.txt - Copy-Item -Path TestDrive:\SourceDirectoryExists TestDrive:\DestinationDirectoryExists\SourceDirectory -Recurse - (Get-Item TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileExists2.txt).Attributes = '' - - # ShouldProcess supported by New-PsDrive - New-PSDrive -PSProvider FileSystem -Name $DriveLetter -Root TestDrive:\MockVhdRoot -scope 1 -} - -$script:vhdDriveLetter = Get-FreeDriveLetter - -# function Mount-Vhd {} -# function Dismount-Vhd {} -# function Get-Disk {} -# function Get-Partition {} -# function Get-Volume {} - -$script:dscFileDirClassName = 'DSC_FileDirectoryConfiguration' -$script:dscNamespace = 'root/microsoft/windows/desiredstateconfiguration' - -Mock -CommandName Mount-Vhd { [PSCustomObject] @{ Path = 'TestDrive:\VhdExists.vhdx' } } - -Mock -CommandName Dismount-Vhd { } - -Mock -CommandName Get-Disk { - New-CimInstance -ClassName MSFT_Disk -Namespace root/Microsoft/Windows/Storage -ClientOnly -} - -Mock -CommandName Get-Partition { - New-CimInstance -ClassName DSC_Partitions -Namespace ROOT/Microsoft/Windows/Storage -ClientOnly | - Add-Member -MemberType NoteProperty -Name Type -Value 'Mocked' -Force -PassThru | - Add-Member -MemberType NoteProperty -Name DriveLetter -Value $script:vhdDriveLetter -PassThru -} - -Mock -CommandName Get-Volume { - New-CimInstance -ClassName DSC_Volumes -Namespace ROOT/Microsoft/Windows/Storage -ClientOnly | - Add-Member -MemberType NoteProperty -Name DriveLetter -Value $script:vhdDriveLetter -PassThru -} - -Mock -CommandName Get-Module { - $true -} -ParameterFilter { $Name -and $Name -eq "Hyper-V" } - -#endregion - -Describe 'DSC_VhdFileDirectory\Get-TargetResource' -Tag 'Get' { - - BeforeAll { - New-TestDriveLayout -DriveLetter $script:vhdDriveLetter - } - - AfterAll { - Remove-PSDrive $script:vhdDriveLetter -ErrorAction SilentlyContinue - } - - It 'Should return a [System.Collections.Hashtable] object type' { - $fdProperties = @{ - SourcePath = 'TestDrive:\FileExists.txt' - DestinationPath = '\DestinationDirectoryExists\' - Type = 'File' - Ensure = 'Present' - } - - $fileDirectory = New-CimInstance -Property $fdProperties -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly - $result = Get-TargetResource -VhdPath TestDrive:\VhdExists.vhdx -FileDirectory $fileDirectory - - $result -is [System.Collections.Hashtable] | - Should -Be $true - } - - #region Testcases for Get-TargetResource - $testCases_Get = @( - @{ - TestName = 'VhdFile exists, Source File exists, Destination File exists' - FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\FileExists.txt' - DestinationPath = 'DestinationDirectoryExists\FileExists.txt' - Type = 'File' - Ensure = 'Present' - } - VhdPath = 'TestDrive:\VhdExists.vhdx' - ExpectedResult = @{ - FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - DestinationPath = $script:vhdDriveLetter + ':\DestinationDirectoryExists\FileExists.txt' - Ensure = 'Present' - } - VhdPath = 'TestDrive:\VhdExists.vhdx' - } - } - @{ - TestName = 'VhdFile exists, Source File exists, Destination File does not exist' - FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\FileExists.txt' - DestinationPath = 'DestinationDirectoryExists\DoesNotExist.txt' - Type = 'File' - Ensure = 'Present' - } - VhdPath = 'TestDrive:\VhdExists.vhdx' - ExpectedResult = @{ - FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - DestinationPath = $script:vhdDriveLetter + ':\DestinationDirectoryExists\DoesNotExist.txt' - Ensure = 'Absent' - } - VhdPath = 'TestDrive:\VhdExists.vhdx' - } - } - @{ - TestName = 'VhdFile exists, Source File does not exist, Destination File exists' - FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\DoesNotExist.txt' - DestinationPath = 'DestinationDirectoryExists\FileExists.txt' - Type = 'File' - Ensure = 'Present' - } - VhdPath = 'TestDrive:\VhdExists.vhdx' - ExpectedResult = @{ - FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - DestinationPath = $script:vhdDriveLetter + ':\DestinationDirectoryExists\FileExists.txt' - Ensure = 'Present' - } - VhdPath = 'TestDrive:\VhdExists.vhdx' - } - } - @{ - TestName = 'VhdFile exists, Source File does not exist, Destination File does not exist' - FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\DoesNotExist.txt' - DestinationPath = 'DestinationDirectoryExists\DoesNotExist.txt' - Type = 'File' - Ensure = 'Present' - } - VhdPath = 'TestDrive:\VhdExists.vhdx' - ExpectedResult = @{ - FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - DestinationPath = $script:vhdDriveLetter + ':\DestinationDirectoryExists\DoesNotExist.txt' - Ensure = 'Absent' - } - VhdPath = 'TestDrive:\VhdExists.vhdx' - } - } - @{ - TestName = 'Vhd does not exist, Source File exists, Destination Path does not exist' - FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\FileExists.txt' - DestinationPath = 'DoesNotExist\' - Type = 'File' - Ensure = 'Present' - } - VhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' - ExpectedResult = @{ - FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - DestinationPath = 'TestDrive:\VhdDoesNotExist.vhdx' - Ensure = 'Absent' - } - VhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' - } - } - @{ - TestName = 'Vhd does not exist, Source File does not exist, Destination Path does not exist' - FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\DoesNotExist.txt' - DestinationPath = 'DoesNotExist\' - Type = 'File' - Ensure = 'Present' - } - VhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' - ExpectedResult = @{ - FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - DestinationPath = 'TestDrive:\VhdDoesNotExist.vhdx' - Ensure = 'Absent' - } - VhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' - } - } - ) - #endRegion - - It 'Should correctly return state when: ' -TestCases $testCases_Get { - param( - $FileDirectoryProperties, - $VhdPath, - $ExpectedResult - ) - - $result = Get-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectoryProperties - - $result['FileDirectory'].CimInstanceProperties.Value | - Should -Be $ExpectedResult['FileDirectory'].CimInstanceProperties.Value - - $result['VhdPath'] | - Should -Be $ExpectedResult['VhdPath'] - } -} - -Describe "DSC_VhdFileDirectory\Test-TargetResource" -Tag 'Test' { - - BeforeAll { - New-TestDriveLayout -DriveLetter $script:vhdDriveLetter - } - - AfterAll { - Remove-PSDrive $script:vhdDriveLetter -ErrorAction SilentlyContinue - } - - Context 'When the system is in the desired state' { - - $testCases_Test_InDesiredState = @( - @{ - TestName = 'VhdPath exists, Destination File exists, DestinationPath includes filename' - VhdPath = 'TestDrive:\VhdExists.vhdx' - FileDirectory = ( - New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\FileExists.txt' - DestinationPath = '\DestinationDirectoryExists\FileExists.txt' - Ensure = 'Present' - } - ) - } - @{ - TestName = 'VhdPath exists, Destination File exists, "Archive" attribute specified and set on file' - VhdPath = 'TestDrive:\VhdExists.vhdx' - FileDirectory = ( - New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\FileExists.txt' - DestinationPath = '\DestinationDirectoryExists\FileExists.txt' - Attributes = 'Archive' - Ensure = 'Present' - } - ) - } - @{ - TestName = 'VhdPath exists, Destination File exists, DestinationPath does not include filename' - VhdPath = 'TestDrive:\VhdExists.vhdx' - FileDirectory = ( - New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\FileExists.txt' - DestinationPath = '\DestinationDirectoryExists' - Ensure = 'Present' - } - ) - } - @{ - TestName = 'Source is Directory, exists at destination' - VhdPath = 'TestDrive:\VhdExists.vhdx' - FileDirectory = ( - New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\SourceDirectoryExists' - DestinationPath = '\DestinationDirectoryExists' - Ensure = 'Present' - } - ) - } - ) - - It 'Should return [$true] when ' -TestCases $testCases_Test_InDesiredState { - param ( - $VhdPath, - $FileDirectory - ) - - $result = Test-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectory - $result | Should -Be $true - } - } - - Context 'When the system is not in the desired state' { - $testCases_Test_NotInDesiredState = @( - @{ - TestName = 'VhdPath exists, Destination File does not exist, DestinationPath includes Filename' - VhdPath = 'TestDrive:\VhdExists.vhdx' - FileDirectory = ( - New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\FileExists.txt' - DestinationPath = '\DestinationDirectoryExists\DoesNotExist.txt' - Ensure = 'Present' - } - ) - } - @{ - TestName = 'VhdPath exists, Destination File does not exist, DestinationPath does not include Filename' - VhdPath = 'TestDrive:\VhdExists.vhdx' - FileDirectory = ( - New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\FileExists3.txt' - DestinationPath = '\DestinationDirectoryExists' - Ensure = 'Present' - } - ) - } - @{ - TestName = 'Destination File exists, but "Ensure" is set to "Absent"' - VhdPath = 'TestDrive:\VhdExists.vhdx' - FileDirectory = ( - New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\FileExists.txt' - DestinationPath = '\DestinationDirectoryExists\FileExists.txt' - Ensure = 'Absent' - } - ) - } - @{ - TestName = 'Destination File exists, "Archive" attribute specified but not set on file' - VhdPath = 'TestDrive:\VhdExists.vhdx' - FileDirectory = ( - New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\FileExists2.txt' - DestinationPath = '\DestinationDirectoryExists\FileExists2.txt' - Attributes = 'Archive' - Ensure = 'Present' - } - ) - } - ) - - It 'Should return [$false] when ' -TestCases $testCases_Test_NotInDesiredState { - param ( - $VhdPath, - $FileDirectory - ) - - $result = Test-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectory - $result | Should -Be $false - } - - It 'Should throw error when VhdPath does not exist' { - $vhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' - $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\FileExists.txt' - DestinationPath = '\DestinationDirectoryExists\DoesNotExist.txt' - Ensure = 'Present' - } - { Test-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory } | - Should -Throw "VHD does not exist in the specified path $vhdPath" - } - } -} - -Describe "DSC_VhdFileDirectory\Set-TargetResource" -Tag 'Set' { - BeforeAll { - New-TestDriveLayout -DriveLetter $script:vhdDriveLetter - } - - AfterAll { - Remove-PSDrive $script:vhdDriveLetter -ErrorAction SilentlyContinue - } - - Context 'When the system is in the desired state' { - $testCases_Set_InDesiredState = @( - @{ - TestName = 'not throw' - VhdPath = 'TestDrive:\VhdExists.vhdx' - FileDirectory = ( - New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\FileExists.txt' - DestinationPath = '\DestinationDirectoryExists\FileExists.txt' - Ensure = 'Present' - } - ) - ExpectedResult = $null - } - ) - - It 'Should ' -TestCases $testCases_Set_InDesiredState { - param ( - $VhdPath, - $FileDirectory, - $ExpectedResult - ) - - { Set-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectory } | Should -Not -throw - } - } - - Context 'When the system is not in the desired state' { - - It 'Should copy the source file to DestinationPath' { - $vhdPath = 'TestDrive:\VhdExists.vhdx' - $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\FileExists.txt' - DestinationPath = '\DestinationDirectoryExists\FileDoesNotExist.txt' - Ensure = 'Present' - } - - Set-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectory - - (Get-FileHash TestDrive:\FileExists.txt).Hash | - Should -Be (Get-FileHash TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileDoesNotExist.txt).hash - } - - It 'Should Insert content into file when "Content" is specified' { - $vhdPath = 'TestDrive:\VhdExists.vhdx' - $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - Content = 'This is some text' - DestinationPath = '\DestinationDirectoryExists\FileDoesNotExist2.txt' - Ensure = 'Present' - } - - Set-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory - - Get-Content TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileDoesNotExist2.txt | - Should -Be 'This is some text' - } - - It 'Should set "hidden" attribute when specified for nonexistent file' { - $vhdPath = 'TestDrive:\VhdExists.vhdx' - $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\FileExists.txt' - DestinationPath = '\DestinationDirectoryExists\FileDoesNotExist3.txt' - Ensure = 'Present' - Attributes = 'Hidden' - } - - Set-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory - - (Get-Item TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileDoesNotExist3.txt -Force).Attributes | - Should -Be 'Hidden' - } - - It 'Should remove the file when "Ensure" is set to "Absent"' { - $vhdPath = 'TestDrive:\VhdExists.vhdx' - $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\FileExists.txt' - DestinationPath = '\DestinationDirectoryExists\FileExists.txt' - Ensure = 'Absent' - } - - Set-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory - - Test-Path TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileExists.txt | - Should -Be $false - } - - It 'Should throw error when VhdPath does not exist' { - $vhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' - $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ - SourcePath = 'TestDrive:\FileExists.txt' - DestinationPath = '\DestinationDirectoryDoesNotExist\FileDoesNotExist.txt' - Ensure = 'Present' - } - - { Set-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory } | - Should -Throw "Specified destination path $vhdPath does not exist!" - } - } -} -} -} -finally -{ - Invoke-TestCleanup -} +# $script:dscModuleName = 'HyperVDsc' +# $script:dscResourceName = 'DSC_VhdFileDirectory' + +# function Invoke-TestSetup +# { +# try +# { +# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' +# } +# catch [System.IO.FileNotFoundException] +# { +# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' +# } + +# $script:testEnvironment = Initialize-TestEnvironment ` +# -DSCModuleName $script:dscModuleName ` +# -DSCResourceName $script:dscResourceName ` +# -ResourceType 'Mof' ` +# -TestType 'Unit' + +# # Import the stub functions. +# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +# } + +# function Invoke-TestCleanup +# { +# Restore-TestEnvironment -TestEnvironment $script:testEnvironment +# } + +# Invoke-TestSetup + +# try +# { +# InModuleScope $script:dscResourceName { + +# #region Functions, Variables and Mocks +# function Get-FreeDriveLetter +# { +# [CmdletBinding()] +# param() + +# $upperCaseChars = 67..90 | ForEach-Object { [char]$_ } +# $driveLettersInUse = Get-PsDrive | Where-Object -FilterScript { +# $upperCaseChars -contains $_.name +# } | Select-Object -ExpandProperty Name + +# foreach ($char in $upperCaseChars) +# { +# if ($driveLettersInUse -notcontains $char) +# { +# Write-Verbose "Selecting $char to use as VhdDriveLetter" + +# return $char +# break +# } +# } +# } + +# function New-TestDriveLayout +# { +# [CmdletBinding(SupportsShouldProcess, ConfirmImpact = "Medium")] +# param( +# [Parameter()] +# [System.String] +# $DriveLetter +# ) + +# # Source file structure +# New-item -Path TestDrive:\VhdExists.vhdx +# 'TestFile1' | Out-File TestDrive:\FileExists.txt +# 'TestFile2' | Out-File TestDrive:\FileExists2.txt +# 'TestFile3' | Out-File TestDrive:\FileExists3.txt +# New-Item -Path TestDrive:\SourceDirectoryExists -ItemType Directory +# New-Item -Path TestDrive:\SourceDirectoryExists2 -ItemType Directory +# 'Some Text' | Out-File TestDrive:\SourceDirectoryExists\File1.txt +# 'Some More Text' | Out-File TestDrive:\SourceDirectoryExists2\File2.txt + +# # VhdRoot structure +# New-Item -Path TestDrive:\MockVhdRoot -ItemType Directory +# New-Item -Path TestDrive:\MockVhdRoot\DestinationDirectoryExists -ItemType Directory +# Copy-Item -Path TestDrive:\FileExists.txt -Destination TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileExists.txt +# Copy-Item -Path TestDrive:\FileExists2.txt -Destination TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileExists2.txt +# Copy-Item -Path TestDrive:\SourceDirectoryExists TestDrive:\DestinationDirectoryExists\SourceDirectory -Recurse +# (Get-Item TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileExists2.txt).Attributes = '' + +# # ShouldProcess supported by New-PsDrive +# New-PSDrive -PSProvider FileSystem -Name $DriveLetter -Root TestDrive:\MockVhdRoot -scope 1 +# } + +# $script:vhdDriveLetter = Get-FreeDriveLetter + +# # function Mount-Vhd {} +# # function Dismount-Vhd {} +# # function Get-Disk {} +# # function Get-Partition {} +# # function Get-Volume {} + +# $script:dscFileDirClassName = 'DSC_FileDirectoryConfiguration' +# $script:dscNamespace = 'root/microsoft/windows/desiredstateconfiguration' + +# Mock -CommandName Mount-Vhd { [PSCustomObject] @{ Path = 'TestDrive:\VhdExists.vhdx' } } + +# Mock -CommandName Dismount-Vhd { } + +# Mock -CommandName Get-Disk { +# New-CimInstance -ClassName MSFT_Disk -Namespace root/Microsoft/Windows/Storage -ClientOnly +# } + +# Mock -CommandName Get-Partition { +# New-CimInstance -ClassName DSC_Partitions -Namespace ROOT/Microsoft/Windows/Storage -ClientOnly | +# Add-Member -MemberType NoteProperty -Name Type -Value 'Mocked' -Force -PassThru | +# Add-Member -MemberType NoteProperty -Name DriveLetter -Value $script:vhdDriveLetter -PassThru +# } + +# Mock -CommandName Get-Volume { +# New-CimInstance -ClassName DSC_Volumes -Namespace ROOT/Microsoft/Windows/Storage -ClientOnly | +# Add-Member -MemberType NoteProperty -Name DriveLetter -Value $script:vhdDriveLetter -PassThru +# } + +# Mock -CommandName Get-Module { +# $true +# } -ParameterFilter { $Name -and $Name -eq "Hyper-V" } + +# #endregion + +# Describe 'DSC_VhdFileDirectory\Get-TargetResource' -Tag 'Get' { + +# BeforeAll { +# New-TestDriveLayout -DriveLetter $script:vhdDriveLetter +# } + +# AfterAll { +# Remove-PSDrive $script:vhdDriveLetter -ErrorAction SilentlyContinue +# } + +# It 'Should return a [System.Collections.Hashtable] object type' { +# $fdProperties = @{ +# SourcePath = 'TestDrive:\FileExists.txt' +# DestinationPath = '\DestinationDirectoryExists\' +# Type = 'File' +# Ensure = 'Present' +# } + +# $fileDirectory = New-CimInstance -Property $fdProperties -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly +# $result = Get-TargetResource -VhdPath TestDrive:\VhdExists.vhdx -FileDirectory $fileDirectory + +# $result -is [System.Collections.Hashtable] | +# Should -Be $true +# } + +# #region Testcases for Get-TargetResource +# $testCases_Get = @( +# @{ +# TestName = 'VhdFile exists, Source File exists, Destination File exists' +# FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\FileExists.txt' +# DestinationPath = 'DestinationDirectoryExists\FileExists.txt' +# Type = 'File' +# Ensure = 'Present' +# } +# VhdPath = 'TestDrive:\VhdExists.vhdx' +# ExpectedResult = @{ +# FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# DestinationPath = $script:vhdDriveLetter + ':\DestinationDirectoryExists\FileExists.txt' +# Ensure = 'Present' +# } +# VhdPath = 'TestDrive:\VhdExists.vhdx' +# } +# } +# @{ +# TestName = 'VhdFile exists, Source File exists, Destination File does not exist' +# FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\FileExists.txt' +# DestinationPath = 'DestinationDirectoryExists\DoesNotExist.txt' +# Type = 'File' +# Ensure = 'Present' +# } +# VhdPath = 'TestDrive:\VhdExists.vhdx' +# ExpectedResult = @{ +# FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# DestinationPath = $script:vhdDriveLetter + ':\DestinationDirectoryExists\DoesNotExist.txt' +# Ensure = 'Absent' +# } +# VhdPath = 'TestDrive:\VhdExists.vhdx' +# } +# } +# @{ +# TestName = 'VhdFile exists, Source File does not exist, Destination File exists' +# FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\DoesNotExist.txt' +# DestinationPath = 'DestinationDirectoryExists\FileExists.txt' +# Type = 'File' +# Ensure = 'Present' +# } +# VhdPath = 'TestDrive:\VhdExists.vhdx' +# ExpectedResult = @{ +# FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# DestinationPath = $script:vhdDriveLetter + ':\DestinationDirectoryExists\FileExists.txt' +# Ensure = 'Present' +# } +# VhdPath = 'TestDrive:\VhdExists.vhdx' +# } +# } +# @{ +# TestName = 'VhdFile exists, Source File does not exist, Destination File does not exist' +# FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\DoesNotExist.txt' +# DestinationPath = 'DestinationDirectoryExists\DoesNotExist.txt' +# Type = 'File' +# Ensure = 'Present' +# } +# VhdPath = 'TestDrive:\VhdExists.vhdx' +# ExpectedResult = @{ +# FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# DestinationPath = $script:vhdDriveLetter + ':\DestinationDirectoryExists\DoesNotExist.txt' +# Ensure = 'Absent' +# } +# VhdPath = 'TestDrive:\VhdExists.vhdx' +# } +# } +# @{ +# TestName = 'Vhd does not exist, Source File exists, Destination Path does not exist' +# FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\FileExists.txt' +# DestinationPath = 'DoesNotExist\' +# Type = 'File' +# Ensure = 'Present' +# } +# VhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' +# ExpectedResult = @{ +# FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# DestinationPath = 'TestDrive:\VhdDoesNotExist.vhdx' +# Ensure = 'Absent' +# } +# VhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' +# } +# } +# @{ +# TestName = 'Vhd does not exist, Source File does not exist, Destination Path does not exist' +# FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\DoesNotExist.txt' +# DestinationPath = 'DoesNotExist\' +# Type = 'File' +# Ensure = 'Present' +# } +# VhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' +# ExpectedResult = @{ +# FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# DestinationPath = 'TestDrive:\VhdDoesNotExist.vhdx' +# Ensure = 'Absent' +# } +# VhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' +# } +# } +# ) +# #endRegion + +# It 'Should correctly return state when: ' -TestCases $testCases_Get { +# param( +# $FileDirectoryProperties, +# $VhdPath, +# $ExpectedResult +# ) + +# $result = Get-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectoryProperties + +# $result['FileDirectory'].CimInstanceProperties.Value | +# Should -Be $ExpectedResult['FileDirectory'].CimInstanceProperties.Value + +# $result['VhdPath'] | +# Should -Be $ExpectedResult['VhdPath'] +# } +# } + +# Describe "DSC_VhdFileDirectory\Test-TargetResource" -Tag 'Test' { + +# BeforeAll { +# New-TestDriveLayout -DriveLetter $script:vhdDriveLetter +# } + +# AfterAll { +# Remove-PSDrive $script:vhdDriveLetter -ErrorAction SilentlyContinue +# } + +# Context 'When the system is in the desired state' { + +# $testCases_Test_InDesiredState = @( +# @{ +# TestName = 'VhdPath exists, Destination File exists, DestinationPath includes filename' +# VhdPath = 'TestDrive:\VhdExists.vhdx' +# FileDirectory = ( +# New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\FileExists.txt' +# DestinationPath = '\DestinationDirectoryExists\FileExists.txt' +# Ensure = 'Present' +# } +# ) +# } +# @{ +# TestName = 'VhdPath exists, Destination File exists, "Archive" attribute specified and set on file' +# VhdPath = 'TestDrive:\VhdExists.vhdx' +# FileDirectory = ( +# New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\FileExists.txt' +# DestinationPath = '\DestinationDirectoryExists\FileExists.txt' +# Attributes = 'Archive' +# Ensure = 'Present' +# } +# ) +# } +# @{ +# TestName = 'VhdPath exists, Destination File exists, DestinationPath does not include filename' +# VhdPath = 'TestDrive:\VhdExists.vhdx' +# FileDirectory = ( +# New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\FileExists.txt' +# DestinationPath = '\DestinationDirectoryExists' +# Ensure = 'Present' +# } +# ) +# } +# @{ +# TestName = 'Source is Directory, exists at destination' +# VhdPath = 'TestDrive:\VhdExists.vhdx' +# FileDirectory = ( +# New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\SourceDirectoryExists' +# DestinationPath = '\DestinationDirectoryExists' +# Ensure = 'Present' +# } +# ) +# } +# ) + +# It 'Should return [$true] when ' -TestCases $testCases_Test_InDesiredState { +# param ( +# $VhdPath, +# $FileDirectory +# ) + +# $result = Test-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectory +# $result | Should -Be $true +# } +# } + +# Context 'When the system is not in the desired state' { +# $testCases_Test_NotInDesiredState = @( +# @{ +# TestName = 'VhdPath exists, Destination File does not exist, DestinationPath includes Filename' +# VhdPath = 'TestDrive:\VhdExists.vhdx' +# FileDirectory = ( +# New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\FileExists.txt' +# DestinationPath = '\DestinationDirectoryExists\DoesNotExist.txt' +# Ensure = 'Present' +# } +# ) +# } +# @{ +# TestName = 'VhdPath exists, Destination File does not exist, DestinationPath does not include Filename' +# VhdPath = 'TestDrive:\VhdExists.vhdx' +# FileDirectory = ( +# New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\FileExists3.txt' +# DestinationPath = '\DestinationDirectoryExists' +# Ensure = 'Present' +# } +# ) +# } +# @{ +# TestName = 'Destination File exists, but "Ensure" is set to "Absent"' +# VhdPath = 'TestDrive:\VhdExists.vhdx' +# FileDirectory = ( +# New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\FileExists.txt' +# DestinationPath = '\DestinationDirectoryExists\FileExists.txt' +# Ensure = 'Absent' +# } +# ) +# } +# @{ +# TestName = 'Destination File exists, "Archive" attribute specified but not set on file' +# VhdPath = 'TestDrive:\VhdExists.vhdx' +# FileDirectory = ( +# New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\FileExists2.txt' +# DestinationPath = '\DestinationDirectoryExists\FileExists2.txt' +# Attributes = 'Archive' +# Ensure = 'Present' +# } +# ) +# } +# ) + +# It 'Should return [$false] when ' -TestCases $testCases_Test_NotInDesiredState { +# param ( +# $VhdPath, +# $FileDirectory +# ) + +# $result = Test-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectory +# $result | Should -Be $false +# } + +# It 'Should throw error when VhdPath does not exist' { +# $vhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' +# $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\FileExists.txt' +# DestinationPath = '\DestinationDirectoryExists\DoesNotExist.txt' +# Ensure = 'Present' +# } +# { Test-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory } | +# Should -Throw "VHD does not exist in the specified path $vhdPath" +# } +# } +# } + +# Describe "DSC_VhdFileDirectory\Set-TargetResource" -Tag 'Set' { +# BeforeAll { +# New-TestDriveLayout -DriveLetter $script:vhdDriveLetter +# } + +# AfterAll { +# Remove-PSDrive $script:vhdDriveLetter -ErrorAction SilentlyContinue +# } + +# Context 'When the system is in the desired state' { +# $testCases_Set_InDesiredState = @( +# @{ +# TestName = 'not throw' +# VhdPath = 'TestDrive:\VhdExists.vhdx' +# FileDirectory = ( +# New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\FileExists.txt' +# DestinationPath = '\DestinationDirectoryExists\FileExists.txt' +# Ensure = 'Present' +# } +# ) +# ExpectedResult = $null +# } +# ) + +# It 'Should ' -TestCases $testCases_Set_InDesiredState { +# param ( +# $VhdPath, +# $FileDirectory, +# $ExpectedResult +# ) + +# { Set-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectory } | Should -Not -throw +# } +# } + +# Context 'When the system is not in the desired state' { + +# It 'Should copy the source file to DestinationPath' { +# $vhdPath = 'TestDrive:\VhdExists.vhdx' +# $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\FileExists.txt' +# DestinationPath = '\DestinationDirectoryExists\FileDoesNotExist.txt' +# Ensure = 'Present' +# } + +# Set-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectory + +# (Get-FileHash TestDrive:\FileExists.txt).Hash | +# Should -Be (Get-FileHash TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileDoesNotExist.txt).hash +# } + +# It 'Should Insert content into file when "Content" is specified' { +# $vhdPath = 'TestDrive:\VhdExists.vhdx' +# $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# Content = 'This is some text' +# DestinationPath = '\DestinationDirectoryExists\FileDoesNotExist2.txt' +# Ensure = 'Present' +# } + +# Set-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory + +# Get-Content TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileDoesNotExist2.txt | +# Should -Be 'This is some text' +# } + +# It 'Should set "hidden" attribute when specified for nonexistent file' { +# $vhdPath = 'TestDrive:\VhdExists.vhdx' +# $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\FileExists.txt' +# DestinationPath = '\DestinationDirectoryExists\FileDoesNotExist3.txt' +# Ensure = 'Present' +# Attributes = 'Hidden' +# } + +# Set-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory + +# (Get-Item TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileDoesNotExist3.txt -Force).Attributes | +# Should -Be 'Hidden' +# } + +# It 'Should remove the file when "Ensure" is set to "Absent"' { +# $vhdPath = 'TestDrive:\VhdExists.vhdx' +# $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\FileExists.txt' +# DestinationPath = '\DestinationDirectoryExists\FileExists.txt' +# Ensure = 'Absent' +# } + +# Set-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory + +# Test-Path TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileExists.txt | +# Should -Be $false +# } + +# It 'Should throw error when VhdPath does not exist' { +# $vhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' +# $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ +# SourcePath = 'TestDrive:\FileExists.txt' +# DestinationPath = '\DestinationDirectoryDoesNotExist\FileDoesNotExist.txt' +# Ensure = 'Present' +# } + +# { Set-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory } | +# Should -Throw "Specified destination path $vhdPath does not exist!" +# } +# } +# } +# } +# } +# finally +# { +# Invoke-TestCleanup +# } diff --git a/tests/Unit/HyperVDsc.Common.Tests.ps1 b/tests/Unit/HyperVDsc.Common.Tests.ps1 deleted file mode 100644 index 69a8d01..0000000 --- a/tests/Unit/HyperVDsc.Common.Tests.ps1 +++ /dev/null @@ -1,315 +0,0 @@ -#region HEADER -$script:projectPath = "$PSScriptRoot\..\.." | Convert-Path -$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { - ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and - $(try - { - Test-ModuleManifest -Path $_.FullName -ErrorAction Stop - } - catch - { - $false - }) - }).BaseName - -$script:parentModule = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 -$script:subModulesFolder = Join-Path -Path $script:parentModule.ModuleBase -ChildPath 'Modules' -Remove-Module -Name $script:parentModule -Force -ErrorAction 'SilentlyContinue' - -$script:subModuleName = (Split-Path -Path $PSCommandPath -Leaf) -replace '\.Tests.ps1' -$script:subModuleFile = Join-Path -Path $script:subModulesFolder -ChildPath "$($script:subModuleName)" - -Import-Module $script:subModuleFile -Force -ErrorAction 'Stop' -#endregion HEADER - -# Import the stub functions. -#Get-Module -Name 'Hyper-V' -All | Remove-Module -Force -Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force - -InModuleScope $script:subModuleName { - Describe 'HyperVDsc.Common\Set-VMProperty' { - It "Should throw if VM is running and 'RestartIfNeeded' is False" { - $mockVMName = 'Test' - - Mock -CommandName Get-VM -MockWith { - return @{ - State = 'Running' - } - } - - $setVMPropertyParams = @{ - VMName = $mockVMName - VMCommand = 'Set-VMProcessor' - ChangeProperty = @{ - ResourcePoolName = 'Dummy' - } - } - - { Set-VMProperty @setVMPropertyParams } | Should -Throw ( - $script:localizedData.CannotUpdatePropertiesOnlineError -f $mockVMName, 'Running' - ) - } - - It "Should stop and restart VM when running and 'RestartIfNeeded' is True" { - Mock -CommandName Stop-VM - Mock -CommandName Set-VMProcessor - Mock -CommandName Set-VMState - Mock -CommandName Get-VM -MockWith { - return @{ - State = 'Running' - } - } - - $setVMPropertyParams = @{ - VMName = 'Test' - VMCommand = 'Set-VMProcessor' - ChangeProperty = @{ - ResourcePoolName = 'Dummy' - } - RestartIfNeeded = $true - } - Set-VMProperty @setVMPropertyParams - - Assert-MockCalled -CommandName Set-VMState -ParameterFilter { - $State -eq 'Off' - } -Scope It - - Assert-MockCalled -CommandName Set-VMState -ParameterFilter { - $State -eq 'Running' - } -Scope It - } - - } - - Describe 'HyperVDsc.Common\Set-VMState' { - It 'Should resume VM when current "State" is "Paused" and target state is "Running"' { - Mock -CommandName Resume-VM - Mock -CommandName Wait-VMIPAddress - Mock -CommandName Get-VM -MockWith { - return @{ - State = 'Paused' - } - } - - Set-VMState -Name 'TestVM' -State 'Running' - - Assert-MockCalled -CommandName Resume-VM -Scope It - Assert-MockCalled -CommandName Wait-VMIPAddress -Scope It -Exactly 0 - } - - It 'Should resume VM and wait when current "State" is "Paused" and target state is "Running"' { - Mock -CommandName Resume-VM - Mock -CommandName Wait-VMIPAddress - Mock -CommandName Get-VM -MockWith { - return @{ - State = 'Paused' - } - } - - Set-VMState -Name 'TestVM' -State 'Running' -WaitForIP $true - - Assert-MockCalled -CommandName Resume-VM -Scope It - Assert-MockCalled -CommandName Wait-VMIPAddress -Scope It - } - - It 'Should start VM when current "State" is "Off" and target state is "Running"' { - Mock -CommandName Start-VM - Mock -CommandName Wait-VMIPAddress - Mock -CommandName Get-VM -MockWith { - return @{ - State = 'Off' - } - } - - Set-VMState -Name 'TestVM' -State 'Running' - - Assert-MockCalled -CommandName Start-VM -Scope It - Assert-MockCalled -CommandName Wait-VMIPAddress -Scope It -Exactly 0 - } - - It 'Should start VM and wait when current "State" is "Off" and target state is "Running"' { - Mock -CommandName Start-VM - Mock -CommandName Wait-VMIPAddress - Mock -CommandName Get-VM -MockWith { - return @{ - State = 'Off' - } - } - - Set-VMState -Name 'TestVM' -State 'Running' -WaitForIP $true - - Assert-MockCalled -CommandName Start-VM -Scope It - Assert-MockCalled -CommandName Wait-VMIPAddress -Scope It - } - - It 'Should suspend VM when current "State" is "Running" and target state is "Paused"' { - Mock -CommandName Suspend-VM - Mock -CommandName Get-VM -MockWith { - return @{ - State = 'Running' - } - } - - Set-VMState -Name 'TestVM' -State 'Paused' - - Assert-MockCalled -CommandName Suspend-VM -Scope It - } - - It 'Should stop VM when current "State" is "Running" and target state is "Off"' { - Mock -CommandName Stop-VM - Mock -CommandName Get-VM -MockWith { - return @{ - State = 'Running' - } - } - - Set-VMState -Name 'TestVM' -State 'Off' - - Assert-MockCalled -CommandName Stop-VM -Scope It - } - - It 'Should stop VM when current "State" is "Paused" and target state is "Off"' { - Mock -CommandName Stop-VM - Mock -CommandName Get-VM -MockWith { - return @{ - State = 'Paused' - } - } - - Set-VMState -Name 'TestVM' -State 'Off' - - Assert-MockCalled -CommandName Stop-VM -Scope It - } - } # describe HyperVDsc.Common\Set-VMState -} - -Describe 'HyperVDsc.Common\Wait-VMIPAddress' { - Context 'When VM network adapter reports 2 IP addresses'{ - BeforeAll { - Mock -CommandName Get-VMNetworkAdapter -ModuleName 'HyperVDsc.Common' -MockWith { - return @{ - IpAddresses = @('192.168.0.1', '172.16.0.1') - } - } - } - - It 'Should return without throwing an exception' { - $result = Wait-VMIPAddress -Name 'Test' -Verbose - - $result | Should -BeNullOrEmpty - } - } - - Context 'When VM network adapter reports 2 IP addresses'{ - BeforeAll { - Mock -CommandName Start-Sleep -ModuleName 'HyperVDsc.Common' - Mock -CommandName Get-VMNetworkAdapter -ModuleName 'HyperVDsc.Common' -MockWith { - return $null - } - } - - It 'Should throw the correct exception' { - { Wait-VMIPAddress -Name 'Test' -Timeout 2 -Verbose } | Should -Throw ( - $script:localizedData.WaitForVMIPAddressTimeoutError -f 'Test', '2' - ) - } - } -} # describe HyperVDsc.Common\WaitVMIPAddress - -Describe 'HyperVDsc.Common\ConvertTo-TimeSpan' { - It 'Should convert 60 seconds to "System.TimeSpan" of 1 minute' { - $testSeconds = 60 - - $result = ConvertTo-TimeSpan -TimeInterval $testSeconds -TimeIntervalType Seconds - - $result.TotalMinutes | Should -Be 1 - } - - It 'Should convert 60 minutes to "System.TimeSpan" of 60 minutes' { - $testMinutes = 60 - - $result = ConvertTo-TimeSpan -TimeInterval $testMinutes -TimeIntervalType Minutes - - $result.TotalHours | Should -Be 1 - } - - It 'Should convert 48 hours to "System.TimeSpan" of 2 days' { - $testHours = 48 - - $result = ConvertTo-TimeSpan -TimeInterval $testHours -TimeIntervalType Hours - - $result.TotalDays | Should -Be 2 - } - -} # describe HyperVDsc.Common\ConvertTo-TimeSpan - -Describe 'HyperVDsc.Common\ConvertFrom-TimeSpan' { - It 'Should convert a "System.TimeSpan" of 1 minute to 60 seconds' { - $testTimeSpan = New-TimeSpan -Minutes 1 - - $result = ConvertFrom-TimeSpan -TimeSpan $testTimeSpan -TimeSpanType Seconds - - $result | Should -Be 60 - } - - It 'Should convert a "System.TimeSpan" of 1 hour to 60 minutes' { - $testTimeSpan = New-TimeSpan -Hours 1 - - $result = ConvertFrom-TimeSpan -TimeSpan $testTimeSpan -TimeSpanType Minutes - - $result | Should -Be 60 - } - - It 'Should convert a "System.TimeSpan" of 2 dayes to 48 hours' { - $testTimeSpan = New-TimeSpan -Days 2 - - $result = ConvertFrom-TimeSpan -TimeSpan $testTimeSpan -TimeSpanType Hours - - $result | Should -Be 48 - } - -} # describe HyperVDsc.Common\ConvertFrom-TimeSpan - -Describe 'HyperVDsc.Common\Get-VMHyperV' { - BeforeAll { - $mockVMName = 'TestVM' - } - - # Guard mocks - It 'Should not throw when no VM is found' { - Mock -CommandName Get-VM -ModuleName 'HyperVDsc.Common' - - $result = Get-VMHyperV -VMName $mockVMName - - $result | Should -BeNullOrEmpty - } - - It 'Should not throw when one VM is found' { - Mock -CommandName Get-VM -ModuleName 'HyperVDsc.Common' -MockWith { - [PSCustomObject] @{ - Name = $VMName - } - } - - $result = Get-VMHyperV -VMName $mockVMName - - $result.Name | Should -Be $mockVMName - } - - It 'Should throw when more than one VM is found' { - Mock -CommandName Get-VM -ModuleName 'HyperVDsc.Common' -MockWith { - @( - [PSCustomObject] @{ - Name = $VMName - }, - [PSCustomObject] @{ - Name = $VMName - } - ) - } - - { Get-VMHyperV -VMName $mockVMName } | Should -Throw ( - $script:localizedData.MoreThanOneVMExistsError -f $mockVMName - ) - } -} # describe HyperVDsc.Common\Get-VMHyperV diff --git a/tests/Unit/HyperVDsc.Common/Private/Wait-VMIPAddress.Tests.ps1 b/tests/Unit/HyperVDsc.Common/Private/Wait-VMIPAddress.Tests.ps1 new file mode 100644 index 0000000..bf7a354 --- /dev/null +++ b/tests/Unit/HyperVDsc.Common/Private/Wait-VMIPAddress.Tests.ps1 @@ -0,0 +1,64 @@ +#region HEADER +$script:projectPath = "$PSScriptRoot\..\..\..\.." | Convert-Path +$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and + $(try + { + Test-ModuleManifest -Path $_.FullName -ErrorAction Stop + } + catch + { + $false + }) + }).BaseName + +$script:parentModule = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 +$script:subModulesFolder = Join-Path -Path $script:parentModule.ModuleBase -ChildPath 'Modules' +Remove-Module -Name $script:parentModule -Force -ErrorAction 'SilentlyContinue' + +$script:subModuleName = ('{0}.Common' -f $script:projectName) +$script:subModuleFile = Join-Path -Path $script:subModulesFolder -ChildPath "$($script:subModuleName)" + +Import-Module $script:subModuleFile -Force -ErrorAction 'Stop' +#endregion HEADER + +# Import the stub functions. +#Get-Module -Name 'Hyper-V' -All | Remove-Module -Force +Import-Module -Name "$PSScriptRoot/../../Stubs/Hyper-V.stubs.psm1" -Force -DisableNameChecking + +Write-Warning ('ParentModule = {0}' -f $script:parentModule) + +InModuleScope $script:parentModule { + Describe 'Private\Wait-VMIPAddress' { + Context 'When VM network adapter reports 2 IP addresses' { + BeforeAll { + Mock -CommandName Get-VMNetworkAdapter -MockWith { + return @{ + IpAddresses = @('192.168.0.1', '172.16.0.1') + } + } + } + + It 'Should return without throwing an exception' { + $result = Wait-VMIPAddress -Name 'Test' -Verbose + + $result | Should -BeNullOrEmpty + } + } + + Context 'When VM network adapter reports 2 IP addresses' { + BeforeAll { + Mock -CommandName Start-Sleep + Mock -CommandName Get-VMNetworkAdapter -MockWith { + return $null + } + } + + It 'Should throw the correct exception' { + { Wait-VMIPAddress -Name 'Test' -Timeout 2 -Verbose } | Should -Throw ( + $script:localizedData.WaitForVMIPAddressTimeoutError -f 'Test', '2' + ) + } + } + } +} diff --git a/tests/Unit/HyperVDsc.Common/Public/ConvertFrom-TimeSpan.ps1 b/tests/Unit/HyperVDsc.Common/Public/ConvertFrom-TimeSpan.ps1 new file mode 100644 index 0000000..f9694c0 --- /dev/null +++ b/tests/Unit/HyperVDsc.Common/Public/ConvertFrom-TimeSpan.ps1 @@ -0,0 +1,51 @@ +# #region HEADER +# $script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path +# $script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { +# ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and +# $(try +# { +# Test-ModuleManifest -Path $_.FullName -ErrorAction Stop +# } +# catch +# { +# $false +# }) +# }).BaseName + +# $script:parentModule = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 + +# Import-Module $script:parentModule -Force -ErrorAction 'Stop' +# #endregion HEADER + +# # Import the stub functions. +# #Get-Module -Name 'Hyper-V' -All | Remove-Module -Force +# Import-Module -Name "$PSScriptRoot/../../Stubs/Hyper-V.stubs.psm1" -Force + +# InModuleScope $script:parentModule { +# Describe 'Public\ConvertFrom-TimeSpan' { +# It 'Should convert a "System.TimeSpan" of 1 minute to 60 seconds' { +# $testTimeSpan = New-TimeSpan -Minutes 1 + +# $result = ConvertFrom-TimeSpan -TimeSpan $testTimeSpan -TimeSpanType Seconds + +# $result | Should -Be 60 +# } + +# It 'Should convert a "System.TimeSpan" of 1 hour to 60 minutes' { +# $testTimeSpan = New-TimeSpan -Hours 1 + +# $result = ConvertFrom-TimeSpan -TimeSpan $testTimeSpan -TimeSpanType Minutes + +# $result | Should -Be 60 +# } + +# It 'Should convert a "System.TimeSpan" of 2 dayes to 48 hours' { +# $testTimeSpan = New-TimeSpan -Days 2 + +# $result = ConvertFrom-TimeSpan -TimeSpan $testTimeSpan -TimeSpanType Hours + +# $result | Should -Be 48 +# } + +# } +# } diff --git a/tests/Unit/HyperVDsc.Common/Public/ConvertTo-TimeSpan.ps1 b/tests/Unit/HyperVDsc.Common/Public/ConvertTo-TimeSpan.ps1 new file mode 100644 index 0000000..0c8b87c --- /dev/null +++ b/tests/Unit/HyperVDsc.Common/Public/ConvertTo-TimeSpan.ps1 @@ -0,0 +1,51 @@ +# #region HEADER +# $script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path +# $script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { +# ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and +# $(try +# { +# Test-ModuleManifest -Path $_.FullName -ErrorAction Stop +# } +# catch +# { +# $false +# }) +# }).BaseName + +# $script:parentModule = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 + +# Import-Module $script:parentModule -Force -ErrorAction 'Stop' +# #endregion HEADER + +# # Import the stub functions. +# #Get-Module -Name 'Hyper-V' -All | Remove-Module -Force +# Import-Module -Name "$PSScriptRoot/../../Stubs/Hyper-V.stubs.psm1" -Force + +# InModuleScope $script:parentModule { +# Describe 'Public\ConvertTo-TimeSpan' { +# It 'Should convert 60 seconds to "System.TimeSpan" of 1 minute' { +# $testSeconds = 60 + +# $result = ConvertTo-TimeSpan -TimeInterval $testSeconds -TimeIntervalType Seconds + +# $result.TotalMinutes | Should -Be 1 +# } + +# It 'Should convert 60 minutes to "System.TimeSpan" of 60 minutes' { +# $testMinutes = 60 + +# $result = ConvertTo-TimeSpan -TimeInterval $testMinutes -TimeIntervalType Minutes + +# $result.TotalHours | Should -Be 1 +# } + +# It 'Should convert 48 hours to "System.TimeSpan" of 2 days' { +# $testHours = 48 + +# $result = ConvertTo-TimeSpan -TimeInterval $testHours -TimeIntervalType Hours + +# $result.TotalDays | Should -Be 2 +# } + +# } +# } diff --git a/tests/Unit/HyperVDsc.Common/Public/Get-VMHyperV.ps1 b/tests/Unit/HyperVDsc.Common/Public/Get-VMHyperV.ps1 new file mode 100644 index 0000000..728a3d9 --- /dev/null +++ b/tests/Unit/HyperVDsc.Common/Public/Get-VMHyperV.ps1 @@ -0,0 +1,68 @@ +# #region HEADER +# $script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path +# $script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { +# ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and +# $(try +# { +# Test-ModuleManifest -Path $_.FullName -ErrorAction Stop +# } +# catch +# { +# $false +# }) +# }).BaseName + +# $script:parentModule = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 + +# Import-Module $script:parentModule -Force -ErrorAction 'Stop' +# #endregion HEADER + +# # Import the stub functions. +# #Get-Module -Name 'Hyper-V' -All | Remove-Module -Force +# Import-Module -Name "$PSScriptRoot/../Stubs/Hyper-V.stubs.psm1" -Force + +# InModuleScope $script:parentModule { +# Describe 'Public\Get-VMHyperV' { +# BeforeAll { +# $mockVMName = 'TestVM' +# } + +# # Guard mocks +# It 'Should not throw when no VM is found' { +# Mock -CommandName Get-VM + +# $result = Get-VMHyperV -VMName $mockVMName + +# $result | Should -BeNullOrEmpty +# } + +# It 'Should not throw when one VM is found' { +# Mock -CommandName Get-VM -MockWith { +# [PSCustomObject] @{ +# Name = $VMName +# } +# } + +# $result = Get-VMHyperV -VMName $mockVMName + +# $result.Name | Should -Be $mockVMName +# } + +# It 'Should throw when more than one VM is found' { +# Mock -CommandName Get-VM -MockWith { +# @( +# [PSCustomObject] @{ +# Name = $VMName +# }, +# [PSCustomObject] @{ +# Name = $VMName +# } +# ) +# } + +# { Get-VMHyperV -VMName $mockVMName } | Should -Throw ( +# $script:localizedData.MoreThanOneVMExistsError -f $mockVMName +# ) +# } +# } +# } diff --git a/tests/Unit/HyperVDsc.Common/Public/Set-VMProperty.ps1 b/tests/Unit/HyperVDsc.Common/Public/Set-VMProperty.ps1 new file mode 100644 index 0000000..efc987f --- /dev/null +++ b/tests/Unit/HyperVDsc.Common/Public/Set-VMProperty.ps1 @@ -0,0 +1,77 @@ +# #region HEADER +# $script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path +# $script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { +# ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and +# $(try +# { +# Test-ModuleManifest -Path $_.FullName -ErrorAction Stop +# } +# catch +# { +# $false +# }) +# }).BaseName + +# $script:parentModule = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 + +# Import-Module $script:parentModule -Force -ErrorAction 'Stop' +# #endregion HEADER + +# # Import the stub functions. +# #Get-Module -Name 'Hyper-V' -All | Remove-Module -Force +# Import-Module -Name "$PSScriptRoot/../Stubs/Hyper-V.stubs.psm1" -Force + +# InModuleScope $script:parentModule { +# Describe 'Public\Set-VMProperty' { +# It "Should throw if VM is running and 'RestartIfNeeded' is False" { +# $mockVMName = 'Test' + +# Mock -CommandName Get-VM -MockWith { +# return @{ +# State = 'Running' +# } +# } + +# $setVMPropertyParams = @{ +# VMName = $mockVMName +# VMCommand = 'Set-VMProcessor' +# ChangeProperty = @{ +# ResourcePoolName = 'Dummy' +# } +# } + +# { Set-VMProperty @setVMPropertyParams } | Should -Throw ( +# $script:localizedData.CannotUpdatePropertiesOnlineError -f $mockVMName, 'Running' +# ) +# } + +# It "Should stop and restart VM when running and 'RestartIfNeeded' is True" { +# Mock -CommandName Stop-VM +# Mock -CommandName Set-VMProcessor +# Mock -CommandName Set-VMStateHvDsc +# Mock -CommandName Get-VM -MockWith { +# return @{ +# State = 'Running' +# } +# } + +# $setVMPropertyParams = @{ +# VMName = 'Test' +# VMCommand = 'Set-VMProcessor' +# ChangeProperty = @{ +# ResourcePoolName = 'Dummy' +# } +# RestartIfNeeded = $true +# } +# Set-VMProperty @setVMPropertyParams + +# Assert-MockCalled -CommandName Set-VMStateHvDsc -ParameterFilter { +# $State -eq 'Off' +# } -Scope It + +# Assert-MockCalled -CommandName Set-VMStateHvDsc -ParameterFilter { +# $State -eq 'Running' +# } -Scope It +# } +# } +# } diff --git a/tests/Unit/HyperVDsc.Common/Public/Set-VMState.ps1 b/tests/Unit/HyperVDsc.Common/Public/Set-VMState.ps1 new file mode 100644 index 0000000..fce2bf0 --- /dev/null +++ b/tests/Unit/HyperVDsc.Common/Public/Set-VMState.ps1 @@ -0,0 +1,125 @@ +# #region HEADER +# $script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path +# $script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { +# ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and +# $(try +# { +# Test-ModuleManifest -Path $_.FullName -ErrorAction Stop +# } +# catch +# { +# $false +# }) +# }).BaseName + +# $script:parentModule = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 + +# Import-Module $script:parentModule -Force -ErrorAction 'Stop' +# #endregion HEADER + +# # Import the stub functions. +# #Get-Module -Name 'Hyper-V' -All | Remove-Module -Force +# Import-Module -Name "$PSScriptRoot/../Stubs/Hyper-V.stubs.psm1" -Force + +# InModuleScope $script:parentModule { +# Describe 'Public\Set-VMState' { +# It 'Should resume VM when current "State" is "Paused" and target state is "Running"' { +# Mock -CommandName Resume-VM +# Mock -CommandName Wait-VMIPAddress +# Mock -CommandName Get-VM -MockWith { +# return @{ +# State = 'Paused' +# } +# } + +# Set-VMState -Name 'TestVM' -State 'Running' + +# Assert-MockCalled -CommandName Resume-VM -Scope It +# Assert-MockCalled -CommandName Wait-VMIPAddress -Scope It -Exactly 0 +# } + +# It 'Should resume VM and wait when current "State" is "Paused" and target state is "Running"' { +# Mock -CommandName Resume-VM +# Mock -CommandName Wait-VMIPAddress +# Mock -CommandName Get-VM -MockWith { +# return @{ +# State = 'Paused' +# } +# } + +# Set-VMState -Name 'TestVM' -State 'Running' -WaitForIP $true + +# Assert-MockCalled -CommandName Resume-VM -Scope It +# Assert-MockCalled -CommandName Wait-VMIPAddress -Scope It +# } + +# It 'Should start VM when current "State" is "Off" and target state is "Running"' { +# Mock -CommandName Start-VM +# Mock -CommandName Wait-VMIPAddress +# Mock -CommandName Get-VM -MockWith { +# return @{ +# State = 'Off' +# } +# } + +# Set-VMState -Name 'TestVM' -State 'Running' + +# Assert-MockCalled -CommandName Start-VM -Scope It +# Assert-MockCalled -CommandName Wait-VMIPAddress -Scope It -Exactly 0 +# } + +# It 'Should start VM and wait when current "State" is "Off" and target state is "Running"' { +# Mock -CommandName Start-VM +# Mock -CommandName Wait-VMIPAddress +# Mock -CommandName Get-VM -MockWith { +# return @{ +# State = 'Off' +# } +# } + +# Set-VMState -Name 'TestVM' -State 'Running' -WaitForIP $true + +# Assert-MockCalled -CommandName Start-VM -Scope It +# Assert-MockCalled -CommandName Wait-VMIPAddress -Scope It +# } + +# It 'Should suspend VM when current "State" is "Running" and target state is "Paused"' { +# Mock -CommandName Suspend-VM +# Mock -CommandName Get-VM -MockWith { +# return @{ +# State = 'Running' +# } +# } + +# Set-VMState -Name 'TestVM' -State 'Paused' + +# Assert-MockCalled -CommandName Suspend-VM -Scope It +# } + +# It 'Should stop VM when current "State" is "Running" and target state is "Off"' { +# Mock -CommandName Stop-VM +# Mock -CommandName Get-VM -MockWith { +# return @{ +# State = 'Running' +# } +# } + +# Set-VMState -Name 'TestVM' -State 'Off' + +# Assert-MockCalled -CommandName Stop-VM -Scope It +# } + +# It 'Should stop VM when current "State" is "Paused" and target state is "Off"' { +# Mock -CommandName Stop-VM +# Mock -CommandName Get-VM -MockWith { +# return @{ +# State = 'Paused' +# } +# } + +# Set-VMState -Name 'TestVM' -State 'Off' + +# Assert-MockCalled -CommandName Stop-VM -Scope It +# } +# } +# } From 0ba364fa3f0331c5dd4cdb37402126b85fbea74b Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Fri, 31 Jan 2025 16:47:08 +0000 Subject: [PATCH 3/6] Reenable tests --- tests/Unit/DSC_VHD.Tests.ps1 | 548 ++--- tests/Unit/DSC_VMDvdDrive.Tests.ps1 | 1388 ++++++------ tests/Unit/DSC_VMHardDiskDrive.Tests.ps1 | 462 ++-- tests/Unit/DSC_VMHost.Tests.ps1 | 722 +++--- tests/Unit/DSC_VMHyperV.Tests.ps1 | 1928 ++++++++--------- tests/Unit/DSC_VMNetworkAdapter.Tests.ps1 | 704 +++--- tests/Unit/DSC_VMProcessor.Tests.ps1 | 582 ++--- tests/Unit/DSC_VMScsiController.Tests.ps1 | 646 +++--- ...MSwitch_BandwidthReservationMode.Tests.ps1 | 958 ++++---- ...C_VMSwitch_EnableEmbeddedTeaming.Tests.ps1 | 988 ++++----- tests/Unit/DSC_VMSwitch_Id.Tests.ps1 | 752 +++---- tests/Unit/DSC_VhdFileDirectory.Tests.ps1 | 1062 ++++----- 12 files changed, 5370 insertions(+), 5370 deletions(-) diff --git a/tests/Unit/DSC_VHD.Tests.ps1 b/tests/Unit/DSC_VHD.Tests.ps1 index 45d8cf1..3b28e57 100644 --- a/tests/Unit/DSC_VHD.Tests.ps1 +++ b/tests/Unit/DSC_VHD.Tests.ps1 @@ -1,274 +1,274 @@ -# $script:dscModuleName = 'HyperVDsc' -# $script:dscResourceName = 'DSC_Vhd' - -# function Invoke-TestSetup -# { -# try -# { -# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' -# } -# catch [System.IO.FileNotFoundException] -# { -# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' -# } - -# $script:testEnvironment = Initialize-TestEnvironment ` -# -DSCModuleName $script:dscModuleName ` -# -DSCResourceName $script:dscResourceName ` -# -ResourceType 'Mof' ` -# -TestType 'Unit' - -# # Import the stub functions. -# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -# } - -# function Invoke-TestCleanup -# { -# Restore-TestEnvironment -TestEnvironment $script:testEnvironment -# } - -# Invoke-TestSetup - -# try -# { -# InModuleScope $script:dscResourceName { -# Describe 'DSC_Vhd\Get-TargetResource' { -# Context 'Should stop when Hyper-V module is missing' { -# Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } -MockWith { -# return $false -# } - -# It 'Should throw when the module is missing' { -# { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | -# Should -Throw 'Please ensure that Hyper-V role is installed with its PowerShell module' -# } -# } - -# # 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 -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } - -# Context 'VHD Present' { -# It 'Should return a hashtable with Ensure being Present' { -# Mock -CommandName Get-VHD -MockWith { -# [pscustomobject]@{ -# Path = 'server.vhdx' -# } -# } - -# $getTargetResult = Get-TargetResource -Name 'server' -Path 'c:\boguspath' -Generation 'vhdx' -# $getTargetResult.Ensure | Should -Be 'Present' -# $getTargetResult | Should -BeOfType hashtable -# } -# } - -# Context 'VHD Not Present' { -# It 'Should return a hashtable with Ensure being Absent' { -# Mock -CommandName Get-VHD - -# $getTargetResult = Get-TargetResource -Name 'server' -Path 'c:\boguspath' -Generation 'vhdx' -# $getTargetResult.Ensure | Should -Be 'Absent' -# $getTargetResult | Should -BeOfType hashtable -# } -# } -# } - -# Describe 'DSC_Vhd\GetNameWithExtension' { -# Context 'Name does not have extension' { -# It 'Should return server.vhdx with generation vhdx' { -# GetNameWithExtension -Name 'server' -Generation 'vhdx' | -# Should -Be 'server.vhdx' -# } - -# It 'Should return server.vhd with generation vhd' { -# GetNameWithExtension -Name 'server' -Generation 'vhd' | -# Should -Be 'server.vhd' -# } - -# It 'Should not throw' { -# { GetNameWithExtension -Name 'server' -Generation 'vhd' } | -# Should -Not -throw -# } -# } - -# Context 'Name has extension' { -# It 'Should return server.vhdx with Name server.vhdx and generation vhdx' { -# GetNameWithExtension -Name 'server.vhd' -Generation 'vhd' | -# Should -Be 'server.vhd' -# } - -# It 'Should throw with mismatch with extension from name and generation' { -# { GetNameWithExtension -Name 'server.vhdx' -Generation 'vhd' } | -# Should -Throw 'the extension vhdx on the name does not match the generation vhd' -# } -# } -# } - -# Describe 'DSC_Vhd\Test-TargetResource' { -# # Create an empty function to be able to mock the missing Hyper-V cmdlet -# function Test-VHD -# { - -# } - -# Context 'Should stop when Hyper-V module is missing' { -# Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } -MockWith { -# return $false -# } - -# It 'Should throw when the module is missing' { -# { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | -# Should -Throw 'Please ensure that Hyper-V role is installed with its PowerShell module' -# } -# } - -# # 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 -# } - -# Context 'Parameter validation' { -# It 'Fixed and Dynamic VHDs need MaximumSizeBytes specified' { -# { Test-TargetResource -Name 'server' -Path 'C:\VMs' -Type 'Dynamic' } | -# Should -Throw 'Specify MaximumSizeBytes property for Fixed and Dynamic VHDs.' -# } - -# It 'Parent Path is passed for a non Differencing disk' { -# { Test-TargetResource -Name 'server' -Path 'C:\VMs' -ParentPath 'C:\VMs\Parent' -Type 'Fixed' -MaximumSizeBytes 1GB } | -# Should -Throw 'Parent path is only supported for Differencing disks' -# } - -# It 'Differencing disk needs a Parent Path' { -# { Test-TargetResource -Name 'server' -Path 'C:\VMs' -Type 'Differencing' } | -# Should -Throw 'Differencing requires a parent path' -# } -# } - -# Context 'ParentPath specified' { -# It 'Should throw when ParentPath does not exist' { -# Mock -CommandName Test-Path -MockWith { $false } - -# { Test-TargetResource -Name 'server' -Path 'C:\VMs' -Type 'Differencing' -ParentPath 'c:\boguspath' } | -# Should -Throw 'c:\boguspath does not exists' -# } - -# # "Generation $Generation should match ParentPath extension $($ParentPath.Split('.')[-1])" -# It 'Should throw when file extension and generation have a mismatch' { -# Mock -CommandName Test-Path -MockWith { $true } - -# { Test-TargetResource -Name 'server' -Path 'C:\VMs' -Type 'Differencing' -ParentPath 'c:\boguspath.vhd' -Generation 'Vhdx' } | -# Should -Throw 'Generation Vhdx should match ParentPath extension vhd' -# } -# } - -# Context 'Path does not exist' { -# It 'Should throw when the path does not exist' { -# Mock -CommandName Test-Path -MockWith { $false } - -# { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | -# Should -Throw 'C:\VMs does not exists' -# } -# } - -# Context 'Vhd exists' { -# BeforeEach { -# Mock -CommandName Test-Path -MockWith { $true } -# Mock -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } -# Mock -CommandName Test-VHD -MockWith { $true } -# } - -# It 'Should not throw' { -# { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | -# Should -not -throw -# } - -# It 'Should return a boolean and it should be true' { -# $testResult = Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB -# $testResult | Should -BeOfType bool -# $testResult -eq $true | Should -Be $true -# } -# } - -# Context 'Vhd does not exist' { -# BeforeEach { -# Mock -CommandName Test-Path -MockWith { $true } -# Mock -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } -# Mock -CommandName Test-VHD -MockWith { $false } -# } - -# It 'Should not throw' { -# { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | -# Should -not -throw -# } - -# It 'Should return a boolean and it should be false' { -# $testResult = Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB -# $testResult | Should -BeOfType bool -# $testResult -eq $true | Should -Be $false -# } -# } -# } - -# Describe 'DSC_Vhd\Set-TargetResource' { -# Context 'Ensure is Absent' { -# Mock -CommandName Test-Path -MockWith { $true } -# Mock -CommandName Remove-Item -# Mock -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } - -# It 'Should remove when Ensure is Absent and vhdx exists' { -# $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -Ensure 'Absent' -# Assert-MockCalled -CommandName Remove-Item -Times 1 -Exactly -# } -# } - -# Context 'Ensure is Present' { -# BeforeEach { -# Mock -CommandName Get-VHD -MockWith { -# [pscustomobject]@{ -# Path = 'server.vhdx' -# ParentPath = 'c:\boguspath\server.vhdx' -# Size = 1073741824 -# Type = 'Differencing' -# } -# } - -# Mock -CommandName Set-VHD -# Mock -CommandName Resize-VHD -# Mock -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } -# Mock -CommandName New-VHD -# } - -# It 'Should Create a VHD when Ensure is present and no VHD exists yet for non Differencing disk' { -# Mock -CommandName Get-VHD -MockWith { throw } - -# $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -Ensure 'Present' -# Assert-MockCalled -CommandName New-VHD -Exactly -Times 1 -Scope It -# } - -# It 'Should Create a VHD when Ensure is present and no VHD exists yet for Differencing disk' { -# Mock -CommandName Get-VHD -MockWith { throw } - -# $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -Ensure 'Present' -ParentPath 'c:\boguspath\server.vhdx' -Type 'Differencing' -# Assert-MockCalled -CommandName New-VHD -Exactly -Times 1 -Scope It -# } - -# It 'Should resize a VHD which has a different size as intended' { -# $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -MaximumSizeBytes 2GB -Ensure 'Present' -# Assert-MockCalled -CommandName Resize-VHD -Exactly -Times 1 -Scope It -# } - -# It 'Should update the parentpath if it is different from intent' { -# $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -ParentPath 'c:\boguspath2\server.vhdx' -Ensure 'Present' -# Assert-MockCalled -CommandName Set-VHD -Exactly -Times 1 -Scope It -# } -# } -# } -# } -# } -# finally -# { -# Invoke-TestCleanup -# } +$script:dscModuleName = 'HyperVDsc' +$script:dscResourceName = 'DSC_Vhd' + +function Invoke-TestSetup +{ + try + { + Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + } + + $script:testEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:dscModuleName ` + -DSCResourceName $script:dscResourceName ` + -ResourceType 'Mof' ` + -TestType 'Unit' + + # Import the stub functions. + Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +} + +function Invoke-TestCleanup +{ + Restore-TestEnvironment -TestEnvironment $script:testEnvironment +} + +Invoke-TestSetup + +try +{ + InModuleScope $script:dscResourceName { + Describe 'DSC_Vhd\Get-TargetResource' { + Context 'Should stop when Hyper-V module is missing' { + Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } -MockWith { + return $false + } + + It 'Should throw when the module is missing' { + { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | + Should -Throw 'Please ensure that Hyper-V role is installed with its PowerShell module' + } + } + + # 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 -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } + + Context 'VHD Present' { + It 'Should return a hashtable with Ensure being Present' { + Mock -CommandName Get-VHD -MockWith { + [pscustomobject]@{ + Path = 'server.vhdx' + } + } + + $getTargetResult = Get-TargetResource -Name 'server' -Path 'c:\boguspath' -Generation 'vhdx' + $getTargetResult.Ensure | Should -Be 'Present' + $getTargetResult | Should -BeOfType hashtable + } + } + + Context 'VHD Not Present' { + It 'Should return a hashtable with Ensure being Absent' { + Mock -CommandName Get-VHD + + $getTargetResult = Get-TargetResource -Name 'server' -Path 'c:\boguspath' -Generation 'vhdx' + $getTargetResult.Ensure | Should -Be 'Absent' + $getTargetResult | Should -BeOfType hashtable + } + } + } + + Describe 'DSC_Vhd\GetNameWithExtension' { + Context 'Name does not have extension' { + It 'Should return server.vhdx with generation vhdx' { + GetNameWithExtension -Name 'server' -Generation 'vhdx' | + Should -Be 'server.vhdx' + } + + It 'Should return server.vhd with generation vhd' { + GetNameWithExtension -Name 'server' -Generation 'vhd' | + Should -Be 'server.vhd' + } + + It 'Should not throw' { + { GetNameWithExtension -Name 'server' -Generation 'vhd' } | + Should -Not -throw + } + } + + Context 'Name has extension' { + It 'Should return server.vhdx with Name server.vhdx and generation vhdx' { + GetNameWithExtension -Name 'server.vhd' -Generation 'vhd' | + Should -Be 'server.vhd' + } + + It 'Should throw with mismatch with extension from name and generation' { + { GetNameWithExtension -Name 'server.vhdx' -Generation 'vhd' } | + Should -Throw 'the extension vhdx on the name does not match the generation vhd' + } + } + } + + Describe 'DSC_Vhd\Test-TargetResource' { + # Create an empty function to be able to mock the missing Hyper-V cmdlet + function Test-VHD + { + + } + + Context 'Should stop when Hyper-V module is missing' { + Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } -MockWith { + return $false + } + + It 'Should throw when the module is missing' { + { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | + Should -Throw 'Please ensure that Hyper-V role is installed with its PowerShell module' + } + } + + # 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 + } + + Context 'Parameter validation' { + It 'Fixed and Dynamic VHDs need MaximumSizeBytes specified' { + { Test-TargetResource -Name 'server' -Path 'C:\VMs' -Type 'Dynamic' } | + Should -Throw 'Specify MaximumSizeBytes property for Fixed and Dynamic VHDs.' + } + + It 'Parent Path is passed for a non Differencing disk' { + { Test-TargetResource -Name 'server' -Path 'C:\VMs' -ParentPath 'C:\VMs\Parent' -Type 'Fixed' -MaximumSizeBytes 1GB } | + Should -Throw 'Parent path is only supported for Differencing disks' + } + + It 'Differencing disk needs a Parent Path' { + { Test-TargetResource -Name 'server' -Path 'C:\VMs' -Type 'Differencing' } | + Should -Throw 'Differencing requires a parent path' + } + } + + Context 'ParentPath specified' { + It 'Should throw when ParentPath does not exist' { + Mock -CommandName Test-Path -MockWith { $false } + + { Test-TargetResource -Name 'server' -Path 'C:\VMs' -Type 'Differencing' -ParentPath 'c:\boguspath' } | + Should -Throw 'c:\boguspath does not exists' + } + + # "Generation $Generation should match ParentPath extension $($ParentPath.Split('.')[-1])" + It 'Should throw when file extension and generation have a mismatch' { + Mock -CommandName Test-Path -MockWith { $true } + + { Test-TargetResource -Name 'server' -Path 'C:\VMs' -Type 'Differencing' -ParentPath 'c:\boguspath.vhd' -Generation 'Vhdx' } | + Should -Throw 'Generation Vhdx should match ParentPath extension vhd' + } + } + + Context 'Path does not exist' { + It 'Should throw when the path does not exist' { + Mock -CommandName Test-Path -MockWith { $false } + + { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | + Should -Throw 'C:\VMs does not exists' + } + } + + Context 'Vhd exists' { + BeforeEach { + Mock -CommandName Test-Path -MockWith { $true } + Mock -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } + Mock -CommandName Test-VHD -MockWith { $true } + } + + It 'Should not throw' { + { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | + Should -not -throw + } + + It 'Should return a boolean and it should be true' { + $testResult = Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB + $testResult | Should -BeOfType bool + $testResult -eq $true | Should -Be $true + } + } + + Context 'Vhd does not exist' { + BeforeEach { + Mock -CommandName Test-Path -MockWith { $true } + Mock -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } + Mock -CommandName Test-VHD -MockWith { $false } + } + + It 'Should not throw' { + { Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB } | + Should -not -throw + } + + It 'Should return a boolean and it should be false' { + $testResult = Test-TargetResource -Name 'server.vhdx' -Path 'C:\VMs' -Type 'Fixed' -MaximumSizeBytes 1GB + $testResult | Should -BeOfType bool + $testResult -eq $true | Should -Be $false + } + } + } + + Describe 'DSC_Vhd\Set-TargetResource' { + Context 'Ensure is Absent' { + Mock -CommandName Test-Path -MockWith { $true } + Mock -CommandName Remove-Item + Mock -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } + + It 'Should remove when Ensure is Absent and vhdx exists' { + $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -Ensure 'Absent' + Assert-MockCalled -CommandName Remove-Item -Times 1 -Exactly + } + } + + Context 'Ensure is Present' { + BeforeEach { + Mock -CommandName Get-VHD -MockWith { + [pscustomobject]@{ + Path = 'server.vhdx' + ParentPath = 'c:\boguspath\server.vhdx' + Size = 1073741824 + Type = 'Differencing' + } + } + + Mock -CommandName Set-VHD + Mock -CommandName Resize-VHD + Mock -CommandName GetNameWithExtension -MockWith { 'server.vhdx' } + Mock -CommandName New-VHD + } + + It 'Should Create a VHD when Ensure is present and no VHD exists yet for non Differencing disk' { + Mock -CommandName Get-VHD -MockWith { throw } + + $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -Ensure 'Present' + Assert-MockCalled -CommandName New-VHD -Exactly -Times 1 -Scope It + } + + It 'Should Create a VHD when Ensure is present and no VHD exists yet for Differencing disk' { + Mock -CommandName Get-VHD -MockWith { throw } + + $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -Ensure 'Present' -ParentPath 'c:\boguspath\server.vhdx' -Type 'Differencing' + Assert-MockCalled -CommandName New-VHD -Exactly -Times 1 -Scope It + } + + It 'Should resize a VHD which has a different size as intended' { + $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -MaximumSizeBytes 2GB -Ensure 'Present' + Assert-MockCalled -CommandName Resize-VHD -Exactly -Times 1 -Scope It + } + + It 'Should update the parentpath if it is different from intent' { + $null = Set-TargetResource -Name 'server.vhdx' -Path 'TestDrive:\' -ParentPath 'c:\boguspath2\server.vhdx' -Ensure 'Present' + Assert-MockCalled -CommandName Set-VHD -Exactly -Times 1 -Scope It + } + } + } + } +} +finally +{ + Invoke-TestCleanup +} diff --git a/tests/Unit/DSC_VMDvdDrive.Tests.ps1 b/tests/Unit/DSC_VMDvdDrive.Tests.ps1 index e13cb29..ecb892f 100644 --- a/tests/Unit/DSC_VMDvdDrive.Tests.ps1 +++ b/tests/Unit/DSC_VMDvdDrive.Tests.ps1 @@ -1,694 +1,694 @@ -# $script:dscModuleName = 'HyperVDsc' -# $script:dscResourceName = 'DSC_VMDvdDrive' - -# function Invoke-TestSetup -# { -# try -# { -# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' -# } -# catch [System.IO.FileNotFoundException] -# { -# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' -# } - -# $script:testEnvironment = Initialize-TestEnvironment ` -# -DSCModuleName $script:dscModuleName ` -# -DSCResourceName $script:dscResourceName ` -# -ResourceType 'Mof' ` -# -TestType 'Unit' - -# # Import the stub functions. -# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -# } - -# function Invoke-TestCleanup -# { -# Restore-TestEnvironment -TestEnvironment $script:testEnvironment -# } - -# Invoke-TestSetup - -# try -# { -# InModuleScope $script:dscResourceName { -# #region Pester Test Initialization - -# $script:VMName = 'HyperVUnitTestsVM' -# $script:TestISOPath = 'd:\test\test.iso' - -# $script:splatGetDvdDrive = @{ -# VMName = $script:VMName -# ControllerNumber = 0 -# ControllerLocation = 1 -# Verbose = $True -# } -# $script:splatAddDvdDriveNoPath = @{ -# VMName = $script:VMName -# ControllerNumber = 0 -# ControllerLocation = 1 -# Path = '' -# Ensure = 'Present' -# Verbose = $True -# } -# $script:splatAddDvdDrive = @{ -# VMName = $script:VMName -# ControllerNumber = 0 -# ControllerLocation = 1 -# Path = $script:TestISOPath -# Ensure = 'Present' -# Verbose = $True -# } -# $script:splatRemoveDvdDrive = @{ -# VMName = $script:VMName -# ControllerNumber = 0 -# ControllerLocation = 1 -# Ensure = 'Absent' -# Verbose = $True -# } -# $script:mockGetModule = [pscustomobject] @{ -# Name = 'Hyper-V' -# } -# $script:mockGetVM = [pscustomobject] @{ -# Name = $VMName -# } -# $script:mockGetVMScsiController = [pscustomobject] @{ -# VMName = $VMName -# } -# $script:mockGetVMHardDiskDrive = [pscustomobject] @{ -# VMName = $VMName -# } -# $script:mockNoDvdDrive = @{ -# VMName = $script:VMName -# ControllerNumber = 0 -# ControllerLocation = 1 -# Ensure = 'Absent' -# } -# $script:mockDvdDriveWithPath = @{ -# VMName = $script:VMName -# ControllerNumber = 0 -# ControllerLocation = 1 -# Path = $script:TestISOPath -# Ensure = 'Present' -# } -# $script:mockDvdDriveWithDiffPath = @{ -# VMName = $script:VMName -# ControllerNumber = 0 -# ControllerLocation = 1 -# Path = 'd:\diff\diff.iso' -# Ensure = 'Present' -# } -# #endregion - -# #region function Get-TargetResource -# Describe 'DSC_VMDvdDrive\Get-TargetResource' { -# Context 'DVD Drive does not exist' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Test-ParameterValid ` -# -Verifiable - -# Mock ` -# -CommandName Get-VMDvdDrive ` -# -MockWith {} ` -# -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } ` -# -Verifiable - -# It 'should not throw exception' { -# { -# $script:resource = Get-TargetResource @script:splatGetDvdDrive -# } | Should -Not -throw -# } - -# It 'should return expected values' { -# $script:resource.VMName | Should -Be $script:splatGetDvdDrive.VMName -# $script:resource.ControllerNumber | Should -Be $script:splatGetDvdDrive.ControllerNumber -# $script:resource.ControllerLocation | Should -Be $script:splatGetDvdDrive.ControllerLocation -# $script:resource.Path | Should -BeNullOrEmpty -# $script:resource.Ensure | Should -Be 'Absent' -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Test-ParameterValid -Exactly 1 -# Assert-MockCalled -CommandName Get-VMDvdDrive -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } -# } -# } - -# Context 'DVD Drive exists, but has empty path' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Test-ParameterValid ` -# -Verifiable - -# Mock ` -# -CommandName Get-VMDvdDrive ` -# -MockWith { $script:splatAddDvdDriveNoPath } ` -# -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } ` -# -Verifiable - -# It 'should not throw exception' { -# { -# $script:resource = Get-TargetResource @script:splatGetDvdDrive -# } | Should -Not -throw -# } - -# It 'should return expected values' { -# $script:resource.VMName | Should -Be $script:splatGetDvdDrive.VMName -# $script:resource.ControllerNumber | Should -Be $script:splatGetDvdDrive.ControllerNumber -# $script:resource.ControllerLocation | Should -Be $script:splatGetDvdDrive.ControllerLocation -# $script:resource.Path | Should -BeNullOrEmpty -# $script:resource.Ensure | Should -Be 'Present' -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Test-ParameterValid -Exactly 1 -# Assert-MockCalled -CommandName Get-VMDvdDrive -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } -# } -# } - -# Context 'DVD Drive exists, and has a test ISO path' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Test-ParameterValid ` -# -Verifiable - -# Mock ` -# -CommandName Get-VMDvdDrive ` -# -MockWith { $script:splatAddDvdDrive } ` -# -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } ` -# -Verifiable - -# It 'should not throw exception' { -# { -# $script:resource = Get-TargetResource @script:splatGetDvdDrive -# } | Should -Not -throw -# } - -# It 'should return expected values' { -# $script:resource.VMName | Should -Be $script:splatGetDvdDrive.VMName -# $script:resource.ControllerNumber | Should -Be $script:splatGetDvdDrive.ControllerNumber -# $script:resource.ControllerLocation | Should -Be $script:splatGetDvdDrive.ControllerLocation -# $script:resource.Path | Should -Be $script:TestISOPath -# $script:resource.Ensure | Should -Be 'Present' -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Test-ParameterValid -Exactly 1 -# Assert-MockCalled -CommandName Get-VMDvdDrive -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } -# } -# } -# } -# #endregion - -# #region function Set-TargetResource -# Describe 'DSC_VMDvdDrive\Set-TargetResource' { -# Context 'DVD Drive does not exist but should' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Get-TargetResource ` -# -MockWith { $script:mockNoDvdDrive } ` -# -Verifiable - -# Mock ` -# -CommandName Add-VMDvdDrive ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` -# -Verifiable - -# # Mocks that should not be called -# Mock -CommandName Set-VMDvdDrive -# Mock -CommandName Remove-VMDvdDrive - -# It 'should not throw exception' { -# { Set-TargetResource @script:splatAddDvdDriveNoPath } | Should -Not -throw -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 -# Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } -# Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 0 -# Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 0 -# } -# } - -# Context 'DVD Drive does exist and should, path matches' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Get-TargetResource ` -# -MockWith { $script:mockDvdDriveWithPath } ` -# -Verifiable - -# # Mocks that should not be called -# Mock -CommandName Add-VMDvdDrive -# Mock -CommandName Set-VMDvdDrive -# Mock -CommandName Remove-VMDvdDrive - -# It 'should not throw exception' { -# { Set-TargetResource @script:splatAddDvdDrive } | Should -Not -throw -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 -# Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 0 -# Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 0 -# Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 0 -# } -# } - -# Context 'DVD Drive does exist and should, path does not match' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Get-TargetResource ` -# -MockWith { $script:mockDvdDriveWithDiffPath } ` -# -Verifiable - -# Mock ` -# -CommandName Set-VMDvdDrive ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` -# -Verifiable - -# # Mocks that should not be called -# Mock -CommandName Add-VMDvdDrive -# Mock -CommandName Remove-VMDvdDrive - -# It 'should not throw exception' { -# { Set-TargetResource @script:splatAddDvdDrive } | Should -Not -throw -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 -# Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 0 -# Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } -# Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 0 -# } -# } - -# Context 'DVD Drive exists and should not' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Get-TargetResource ` -# -MockWith { $script:mockDvdDriveWithPath } ` -# -Verifiable - -# Mock ` -# -CommandName Remove-VMDvdDrive ` -# -ParameterFilter { $VMName -eq $script:splatRemoveDvdDrive.VMName } ` -# -Verifiable - -# # Mocks that should not be called -# Mock -CommandName Add-VMDvdDrive -# Mock -CommandName Set-VMDvdDrive - -# It 'should not throw exception' { -# { Set-TargetResource @script:splatRemoveDvdDrive } | Should -Not -throw -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 -# Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 0 -# Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 0 -# Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatRemoveDvdDrive.VMName } -# } -# } - -# Context 'DVD Drive does not exist and should not' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Get-TargetResource ` -# -MockWith { $script:mockNoDvdDrive } ` -# -Verifiable - -# # Mocks that should not be called -# Mock -CommandName Add-VMDvdDrive -# Mock -CommandName Set-VMDvdDrive -# Mock -CommandName Remove-VMDvdDrive - -# It 'should not throw exception' { -# { Set-TargetResource @script:splatRemoveDvdDrive } | Should -Not -throw -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 -# Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 0 -# Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 0 -# Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 0 -# } -# } -# } -# #endregion - -# #region function Test-TargetResource -# Describe 'DSC_VMDvdDrive\Test-TargetResource' { -# Context 'DVD Drive does not exist but should' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Get-TargetResource ` -# -MockWith { $script:mockNoDvdDrive } ` -# -Verifiable - -# It 'should return false' { -# Test-TargetResource @script:splatAddDvdDriveNoPath | Should -Be $False -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 -# } -# } - -# Context 'DVD Drive does exist and should, path matches' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Get-TargetResource ` -# -MockWith { $script:mockDvdDriveWithPath } ` -# -Verifiable - -# It 'should return true' { -# Test-TargetResource @script:splatAddDvdDrive | Should -Be $True -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 -# } -# } - -# Context 'DVD Drive does exist and should, path does not match' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Get-TargetResource ` -# -MockWith { $script:mockDvdDriveWithDiffPath } ` -# -Verifiable - -# It 'should return false' { -# Test-TargetResource @script:splatAddDvdDrive | Should -Be $False -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 -# } -# } - -# Context 'DVD Drive exists and should not' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Get-TargetResource ` -# -MockWith { $script:mockDvdDriveWithPath } ` -# -Verifiable - -# It 'should return false' { -# Test-TargetResource @script:splatRemoveDvdDrive | Should -Be $False -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 -# } -# } - -# Context 'DVD Drive does not exist and should not' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Get-TargetResource ` -# -MockWith { $script:mockNoDvdDrive } ` -# -Verifiable - -# It 'should return true' { -# Test-TargetResource @script:splatRemoveDvdDrive | Should -Be $True -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 -# } -# } -# } -# #endregion - -# #region function Test-ParameterValid -# Describe 'DSC_VMDvdDrive\Test-ParameterValid' { -# Context 'Hyper-V Module is not available' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Get-Module ` -# -Verifiable - -# # Mocks that should not be called -# Mock -CommandName Get-VM -# Mock -CommandName Get-VMScsiController -# Mock -CommandName Get-VMIdeController -# Mock -CommandName Get-VMHardDiskDrive - -# It 'should throw exception' { -# $errorMessage = $script:localizedData.RoleMissingError -f 'Hyper-V' - -# { Test-ParameterValid @script:splatAddDvdDriveNoPath } | Should -Throw $errorMessage -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Get-Module -Exactly 1 -# } -# } - -# Context 'VM does not exist' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Get-Module ` -# -MockWith { $script:mockGetModule } ` -# -Verifiable - -# Mock ` -# -CommandName Get-VM ` -# -MockWith { throw } ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` -# -Verifiable - -# # Mocks that should not be called -# Mock -CommandName Get-VMScsiController -# Mock -CommandName Get-VMIdeController -# Mock -CommandName Get-VMHardDiskDrive - -# It 'should throw exception' { -# { Test-ParameterValid @script:splatAddDvdDriveNoPath } | Should -Throw -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Get-Module -Exactly 1 -# Assert-MockCalled -CommandName Get-VM -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } -# } -# } - -# Context 'VM exists, controller does not exist' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Get-Module ` -# -MockWith { $script:mockGetModule } ` -# -Verifiable - -# Mock ` -# -CommandName Get-VM ` -# -MockWith { $script:mockGetVM } ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` -# -Verifiable - -# Mock ` -# -CommandName Get-VMScsiController ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` -# -Verifiable - -# Mock ` -# -CommandName Get-VMIdeController ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` -# -Verifiable - -# # Mocks that should not be called -# Mock -CommandName Get-VMHardDiskDrive - -# It 'should throw exception' { -# $errorMessage = $script:localizedData.VMControllerDoesNotExistError -f $script:VMName, 0 - -# { Test-ParameterValid @script:splatAddDvdDriveNoPath } | Should -Throw $errorMessage -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Get-Module -Exactly 1 -# Assert-MockCalled -CommandName Get-VM -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } -# Assert-MockCalled -CommandName Get-VMScsiController -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } -# Assert-MockCalled -CommandName Get-VMIdeController -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } -# } -# } - -# Context 'VM exists, SCSI controller exists, HD assigned' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Get-Module ` -# -MockWith { $script:mockGetModule } ` -# -Verifiable - -# Mock ` -# -CommandName Get-VM ` -# -MockWith { $script:mockGetVM } ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` -# -Verifiable - -# Mock ` -# -CommandName Get-VMScsiController ` -# -MockWith { $script:mockGetVMScsiController } ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` -# -Verifiable - -# Mock ` -# -CommandName Get-VMHardDiskDrive ` -# -MockWith { $script:mockGetVMHardDiskDrive } ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` -# -Verifiable - -# # Mocks that should not be called -# Mock -CommandName Get-VMIdeController - -# It 'should throw exception' { -# $errorMessage = $script:localizedData.ControllerConflictError -f $script:VMName, 0, 1 - -# { Test-ParameterValid @script:splatAddDvdDriveNoPath } | Should -Throw $errorMessage -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Get-Module -Exactly 1 -# Assert-MockCalled -CommandName Get-VM -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } -# Assert-MockCalled -CommandName Get-VMScsiController -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } -# Assert-MockCalled -CommandName Get-VMHardDiskDrive -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } -# } -# } - -# Context 'VM exists, SCSI controller exists, HD not assigned, Path invalid' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Get-Module ` -# -MockWith { $script:mockGetModule } ` -# -Verifiable - -# Mock ` -# -CommandName Get-VM ` -# -MockWith { $script:mockGetVM } ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` -# -Verifiable - -# Mock ` -# -CommandName Get-VMScsiController ` -# -MockWith { $script:mockGetVMScsiController } ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` -# -Verifiable - -# Mock ` -# -CommandName Get-VMHardDiskDrive ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` -# -Verifiable - -# Mock ` -# -CommandName Test-Path ` -# -MockWith { $False } ` -# -Verifiable - -# # Mocks that should not be called -# Mock -CommandName Get-VMIdeController - -# It 'should throw exception' { -# $errorMessage = $script:localizedData.PathDoesNotExistError -f $script:TestISOPath - -# { Test-ParameterValid @script:splatAddDvdDrive } | Should -Throw $errorMessage -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Get-Module -Exactly 1 -# Assert-MockCalled -CommandName Get-VM -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } -# Assert-MockCalled -CommandName Get-VMScsiController -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } -# Assert-MockCalled -CommandName Get-VMHardDiskDrive -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } -# Assert-MockCalled -CommandName Test-Path -Exactly 1 -# } -# } - -# Context 'VM exists, SCSI contrller exists, HD not assigned, Path Valid' { -# # Verifiable (should be called) mocks -# Mock ` -# -CommandName Get-Module ` -# -MockWith { $script:mockGetModule } ` -# -Verifiable - -# Mock ` -# -CommandName Get-VM ` -# -MockWith { $script:mockGetVM } ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` -# -Verifiable - -# Mock ` -# -CommandName Get-VMScsiController ` -# -MockWith { $script:mockGetVMScsiController } ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` -# -Verifiable - -# Mock ` -# -CommandName Get-VMHardDiskDrive ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` -# -Verifiable - -# Mock ` -# -CommandName Test-Path ` -# -MockWith { $True } ` -# -Verifiable - -# # Mocks that should not be called -# Mock -CommandName Get-VMIdeController - -# It 'should not throw exception' { -# Test-ParameterValid @script:splatAddDvdDrive | Should -Be $True -# } - -# It 'all the get mocks should be called' { -# Assert-VerifiableMock -# Assert-MockCalled -CommandName Get-Module -Exactly 1 -# Assert-MockCalled -CommandName Get-VM -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } -# Assert-MockCalled -CommandName Get-VMScsiController -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } -# Assert-MockCalled -CommandName Get-VMHardDiskDrive -Exactly 1 ` -# -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } -# Assert-MockCalled -CommandName Test-Path -Exactly 1 -# } -# } -# } -# #endregion -# } -# } -# finally -# { -# Invoke-TestCleanup -# } +$script:dscModuleName = 'HyperVDsc' +$script:dscResourceName = 'DSC_VMDvdDrive' + +function Invoke-TestSetup +{ + try + { + Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + } + + $script:testEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:dscModuleName ` + -DSCResourceName $script:dscResourceName ` + -ResourceType 'Mof' ` + -TestType 'Unit' + + # Import the stub functions. + Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +} + +function Invoke-TestCleanup +{ + Restore-TestEnvironment -TestEnvironment $script:testEnvironment +} + +Invoke-TestSetup + +try +{ + InModuleScope $script:dscResourceName { + #region Pester Test Initialization + + $script:VMName = 'HyperVUnitTestsVM' + $script:TestISOPath = 'd:\test\test.iso' + + $script:splatGetDvdDrive = @{ + VMName = $script:VMName + ControllerNumber = 0 + ControllerLocation = 1 + Verbose = $True + } + $script:splatAddDvdDriveNoPath = @{ + VMName = $script:VMName + ControllerNumber = 0 + ControllerLocation = 1 + Path = '' + Ensure = 'Present' + Verbose = $True + } + $script:splatAddDvdDrive = @{ + VMName = $script:VMName + ControllerNumber = 0 + ControllerLocation = 1 + Path = $script:TestISOPath + Ensure = 'Present' + Verbose = $True + } + $script:splatRemoveDvdDrive = @{ + VMName = $script:VMName + ControllerNumber = 0 + ControllerLocation = 1 + Ensure = 'Absent' + Verbose = $True + } + $script:mockGetModule = [pscustomobject] @{ + Name = 'Hyper-V' + } + $script:mockGetVM = [pscustomobject] @{ + Name = $VMName + } + $script:mockGetVMScsiController = [pscustomobject] @{ + VMName = $VMName + } + $script:mockGetVMHardDiskDrive = [pscustomobject] @{ + VMName = $VMName + } + $script:mockNoDvdDrive = @{ + VMName = $script:VMName + ControllerNumber = 0 + ControllerLocation = 1 + Ensure = 'Absent' + } + $script:mockDvdDriveWithPath = @{ + VMName = $script:VMName + ControllerNumber = 0 + ControllerLocation = 1 + Path = $script:TestISOPath + Ensure = 'Present' + } + $script:mockDvdDriveWithDiffPath = @{ + VMName = $script:VMName + ControllerNumber = 0 + ControllerLocation = 1 + Path = 'd:\diff\diff.iso' + Ensure = 'Present' + } + #endregion + + #region function Get-TargetResource + Describe 'DSC_VMDvdDrive\Get-TargetResource' { + Context 'DVD Drive does not exist' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Test-ParameterValid ` + -Verifiable + + Mock ` + -CommandName Get-VMDvdDrive ` + -MockWith {} ` + -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } ` + -Verifiable + + It 'should not throw exception' { + { + $script:resource = Get-TargetResource @script:splatGetDvdDrive + } | Should -Not -throw + } + + It 'should return expected values' { + $script:resource.VMName | Should -Be $script:splatGetDvdDrive.VMName + $script:resource.ControllerNumber | Should -Be $script:splatGetDvdDrive.ControllerNumber + $script:resource.ControllerLocation | Should -Be $script:splatGetDvdDrive.ControllerLocation + $script:resource.Path | Should -BeNullOrEmpty + $script:resource.Ensure | Should -Be 'Absent' + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Test-ParameterValid -Exactly 1 + Assert-MockCalled -CommandName Get-VMDvdDrive -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } + } + } + + Context 'DVD Drive exists, but has empty path' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Test-ParameterValid ` + -Verifiable + + Mock ` + -CommandName Get-VMDvdDrive ` + -MockWith { $script:splatAddDvdDriveNoPath } ` + -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } ` + -Verifiable + + It 'should not throw exception' { + { + $script:resource = Get-TargetResource @script:splatGetDvdDrive + } | Should -Not -throw + } + + It 'should return expected values' { + $script:resource.VMName | Should -Be $script:splatGetDvdDrive.VMName + $script:resource.ControllerNumber | Should -Be $script:splatGetDvdDrive.ControllerNumber + $script:resource.ControllerLocation | Should -Be $script:splatGetDvdDrive.ControllerLocation + $script:resource.Path | Should -BeNullOrEmpty + $script:resource.Ensure | Should -Be 'Present' + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Test-ParameterValid -Exactly 1 + Assert-MockCalled -CommandName Get-VMDvdDrive -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } + } + } + + Context 'DVD Drive exists, and has a test ISO path' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Test-ParameterValid ` + -Verifiable + + Mock ` + -CommandName Get-VMDvdDrive ` + -MockWith { $script:splatAddDvdDrive } ` + -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } ` + -Verifiable + + It 'should not throw exception' { + { + $script:resource = Get-TargetResource @script:splatGetDvdDrive + } | Should -Not -throw + } + + It 'should return expected values' { + $script:resource.VMName | Should -Be $script:splatGetDvdDrive.VMName + $script:resource.ControllerNumber | Should -Be $script:splatGetDvdDrive.ControllerNumber + $script:resource.ControllerLocation | Should -Be $script:splatGetDvdDrive.ControllerLocation + $script:resource.Path | Should -Be $script:TestISOPath + $script:resource.Ensure | Should -Be 'Present' + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Test-ParameterValid -Exactly 1 + Assert-MockCalled -CommandName Get-VMDvdDrive -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatGetDvdDrive.VMName } + } + } + } + #endregion + + #region function Set-TargetResource + Describe 'DSC_VMDvdDrive\Set-TargetResource' { + Context 'DVD Drive does not exist but should' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Get-TargetResource ` + -MockWith { $script:mockNoDvdDrive } ` + -Verifiable + + Mock ` + -CommandName Add-VMDvdDrive ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` + -Verifiable + + # Mocks that should not be called + Mock -CommandName Set-VMDvdDrive + Mock -CommandName Remove-VMDvdDrive + + It 'should not throw exception' { + { Set-TargetResource @script:splatAddDvdDriveNoPath } | Should -Not -throw + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 + Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } + Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 0 + Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 0 + } + } + + Context 'DVD Drive does exist and should, path matches' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Get-TargetResource ` + -MockWith { $script:mockDvdDriveWithPath } ` + -Verifiable + + # Mocks that should not be called + Mock -CommandName Add-VMDvdDrive + Mock -CommandName Set-VMDvdDrive + Mock -CommandName Remove-VMDvdDrive + + It 'should not throw exception' { + { Set-TargetResource @script:splatAddDvdDrive } | Should -Not -throw + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 + Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 0 + Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 0 + Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 0 + } + } + + Context 'DVD Drive does exist and should, path does not match' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Get-TargetResource ` + -MockWith { $script:mockDvdDriveWithDiffPath } ` + -Verifiable + + Mock ` + -CommandName Set-VMDvdDrive ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` + -Verifiable + + # Mocks that should not be called + Mock -CommandName Add-VMDvdDrive + Mock -CommandName Remove-VMDvdDrive + + It 'should not throw exception' { + { Set-TargetResource @script:splatAddDvdDrive } | Should -Not -throw + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 + Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 0 + Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } + Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 0 + } + } + + Context 'DVD Drive exists and should not' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Get-TargetResource ` + -MockWith { $script:mockDvdDriveWithPath } ` + -Verifiable + + Mock ` + -CommandName Remove-VMDvdDrive ` + -ParameterFilter { $VMName -eq $script:splatRemoveDvdDrive.VMName } ` + -Verifiable + + # Mocks that should not be called + Mock -CommandName Add-VMDvdDrive + Mock -CommandName Set-VMDvdDrive + + It 'should not throw exception' { + { Set-TargetResource @script:splatRemoveDvdDrive } | Should -Not -throw + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 + Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 0 + Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 0 + Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatRemoveDvdDrive.VMName } + } + } + + Context 'DVD Drive does not exist and should not' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Get-TargetResource ` + -MockWith { $script:mockNoDvdDrive } ` + -Verifiable + + # Mocks that should not be called + Mock -CommandName Add-VMDvdDrive + Mock -CommandName Set-VMDvdDrive + Mock -CommandName Remove-VMDvdDrive + + It 'should not throw exception' { + { Set-TargetResource @script:splatRemoveDvdDrive } | Should -Not -throw + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 + Assert-MockCalled -CommandName Add-VMDvdDrive -Exactly 0 + Assert-MockCalled -CommandName Set-VMDvdDrive -Exactly 0 + Assert-MockCalled -CommandName Remove-VMDvdDrive -Exactly 0 + } + } + } + #endregion + + #region function Test-TargetResource + Describe 'DSC_VMDvdDrive\Test-TargetResource' { + Context 'DVD Drive does not exist but should' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Get-TargetResource ` + -MockWith { $script:mockNoDvdDrive } ` + -Verifiable + + It 'should return false' { + Test-TargetResource @script:splatAddDvdDriveNoPath | Should -Be $False + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 + } + } + + Context 'DVD Drive does exist and should, path matches' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Get-TargetResource ` + -MockWith { $script:mockDvdDriveWithPath } ` + -Verifiable + + It 'should return true' { + Test-TargetResource @script:splatAddDvdDrive | Should -Be $True + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 + } + } + + Context 'DVD Drive does exist and should, path does not match' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Get-TargetResource ` + -MockWith { $script:mockDvdDriveWithDiffPath } ` + -Verifiable + + It 'should return false' { + Test-TargetResource @script:splatAddDvdDrive | Should -Be $False + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 + } + } + + Context 'DVD Drive exists and should not' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Get-TargetResource ` + -MockWith { $script:mockDvdDriveWithPath } ` + -Verifiable + + It 'should return false' { + Test-TargetResource @script:splatRemoveDvdDrive | Should -Be $False + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 + } + } + + Context 'DVD Drive does not exist and should not' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Get-TargetResource ` + -MockWith { $script:mockNoDvdDrive } ` + -Verifiable + + It 'should return true' { + Test-TargetResource @script:splatRemoveDvdDrive | Should -Be $True + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Get-TargetResource -Exactly 1 + } + } + } + #endregion + + #region function Test-ParameterValid + Describe 'DSC_VMDvdDrive\Test-ParameterValid' { + Context 'Hyper-V Module is not available' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Get-Module ` + -Verifiable + + # Mocks that should not be called + Mock -CommandName Get-VM + Mock -CommandName Get-VMScsiController + Mock -CommandName Get-VMIdeController + Mock -CommandName Get-VMHardDiskDrive + + It 'should throw exception' { + $errorMessage = $script:localizedData.RoleMissingError -f 'Hyper-V' + + { Test-ParameterValid @script:splatAddDvdDriveNoPath } | Should -Throw $errorMessage + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Get-Module -Exactly 1 + } + } + + Context 'VM does not exist' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Get-Module ` + -MockWith { $script:mockGetModule } ` + -Verifiable + + Mock ` + -CommandName Get-VM ` + -MockWith { throw } ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` + -Verifiable + + # Mocks that should not be called + Mock -CommandName Get-VMScsiController + Mock -CommandName Get-VMIdeController + Mock -CommandName Get-VMHardDiskDrive + + It 'should throw exception' { + { Test-ParameterValid @script:splatAddDvdDriveNoPath } | Should -Throw + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Get-Module -Exactly 1 + Assert-MockCalled -CommandName Get-VM -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } + } + } + + Context 'VM exists, controller does not exist' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Get-Module ` + -MockWith { $script:mockGetModule } ` + -Verifiable + + Mock ` + -CommandName Get-VM ` + -MockWith { $script:mockGetVM } ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` + -Verifiable + + Mock ` + -CommandName Get-VMScsiController ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` + -Verifiable + + Mock ` + -CommandName Get-VMIdeController ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` + -Verifiable + + # Mocks that should not be called + Mock -CommandName Get-VMHardDiskDrive + + It 'should throw exception' { + $errorMessage = $script:localizedData.VMControllerDoesNotExistError -f $script:VMName, 0 + + { Test-ParameterValid @script:splatAddDvdDriveNoPath } | Should -Throw $errorMessage + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Get-Module -Exactly 1 + Assert-MockCalled -CommandName Get-VM -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } + Assert-MockCalled -CommandName Get-VMScsiController -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } + Assert-MockCalled -CommandName Get-VMIdeController -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } + } + } + + Context 'VM exists, SCSI controller exists, HD assigned' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Get-Module ` + -MockWith { $script:mockGetModule } ` + -Verifiable + + Mock ` + -CommandName Get-VM ` + -MockWith { $script:mockGetVM } ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` + -Verifiable + + Mock ` + -CommandName Get-VMScsiController ` + -MockWith { $script:mockGetVMScsiController } ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` + -Verifiable + + Mock ` + -CommandName Get-VMHardDiskDrive ` + -MockWith { $script:mockGetVMHardDiskDrive } ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } ` + -Verifiable + + # Mocks that should not be called + Mock -CommandName Get-VMIdeController + + It 'should throw exception' { + $errorMessage = $script:localizedData.ControllerConflictError -f $script:VMName, 0, 1 + + { Test-ParameterValid @script:splatAddDvdDriveNoPath } | Should -Throw $errorMessage + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Get-Module -Exactly 1 + Assert-MockCalled -CommandName Get-VM -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } + Assert-MockCalled -CommandName Get-VMScsiController -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } + Assert-MockCalled -CommandName Get-VMHardDiskDrive -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDriveNoPath.VMName } + } + } + + Context 'VM exists, SCSI controller exists, HD not assigned, Path invalid' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Get-Module ` + -MockWith { $script:mockGetModule } ` + -Verifiable + + Mock ` + -CommandName Get-VM ` + -MockWith { $script:mockGetVM } ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` + -Verifiable + + Mock ` + -CommandName Get-VMScsiController ` + -MockWith { $script:mockGetVMScsiController } ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` + -Verifiable + + Mock ` + -CommandName Get-VMHardDiskDrive ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` + -Verifiable + + Mock ` + -CommandName Test-Path ` + -MockWith { $False } ` + -Verifiable + + # Mocks that should not be called + Mock -CommandName Get-VMIdeController + + It 'should throw exception' { + $errorMessage = $script:localizedData.PathDoesNotExistError -f $script:TestISOPath + + { Test-ParameterValid @script:splatAddDvdDrive } | Should -Throw $errorMessage + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Get-Module -Exactly 1 + Assert-MockCalled -CommandName Get-VM -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } + Assert-MockCalled -CommandName Get-VMScsiController -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } + Assert-MockCalled -CommandName Get-VMHardDiskDrive -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } + Assert-MockCalled -CommandName Test-Path -Exactly 1 + } + } + + Context 'VM exists, SCSI contrller exists, HD not assigned, Path Valid' { + # Verifiable (should be called) mocks + Mock ` + -CommandName Get-Module ` + -MockWith { $script:mockGetModule } ` + -Verifiable + + Mock ` + -CommandName Get-VM ` + -MockWith { $script:mockGetVM } ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` + -Verifiable + + Mock ` + -CommandName Get-VMScsiController ` + -MockWith { $script:mockGetVMScsiController } ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` + -Verifiable + + Mock ` + -CommandName Get-VMHardDiskDrive ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } ` + -Verifiable + + Mock ` + -CommandName Test-Path ` + -MockWith { $True } ` + -Verifiable + + # Mocks that should not be called + Mock -CommandName Get-VMIdeController + + It 'should not throw exception' { + Test-ParameterValid @script:splatAddDvdDrive | Should -Be $True + } + + It 'all the get mocks should be called' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Get-Module -Exactly 1 + Assert-MockCalled -CommandName Get-VM -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } + Assert-MockCalled -CommandName Get-VMScsiController -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } + Assert-MockCalled -CommandName Get-VMHardDiskDrive -Exactly 1 ` + -ParameterFilter { $VMName -eq $script:splatAddDvdDrive.VMName } + Assert-MockCalled -CommandName Test-Path -Exactly 1 + } + } + } + #endregion + } +} +finally +{ + Invoke-TestCleanup +} diff --git a/tests/Unit/DSC_VMHardDiskDrive.Tests.ps1 b/tests/Unit/DSC_VMHardDiskDrive.Tests.ps1 index 8ca71cd..60ae4cc 100644 --- a/tests/Unit/DSC_VMHardDiskDrive.Tests.ps1 +++ b/tests/Unit/DSC_VMHardDiskDrive.Tests.ps1 @@ -1,276 +1,276 @@ -# $script:dscModuleName = 'HyperVDsc' -# $script:dscResourceName = 'DSC_VMHardDiskDrive' +$script:dscModuleName = 'HyperVDsc' +$script:dscResourceName = 'DSC_VMHardDiskDrive' -# function Invoke-TestSetup -# { -# try -# { -# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' -# } -# catch [System.IO.FileNotFoundException] -# { -# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' -# } +function Invoke-TestSetup +{ + try + { + Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + } -# $script:testEnvironment = Initialize-TestEnvironment ` -# -DSCModuleName $script:dscModuleName ` -# -DSCResourceName $script:dscResourceName ` -# -ResourceType 'Mof' ` -# -TestType 'Unit' + $script:testEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:dscModuleName ` + -DSCResourceName $script:dscResourceName ` + -ResourceType 'Mof' ` + -TestType 'Unit' -# # Import the stub functions. -# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -# } + # Import the stub functions. + Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +} -# function Invoke-TestCleanup -# { -# Restore-TestEnvironment -TestEnvironment $script:testEnvironment -# } +function Invoke-TestCleanup +{ + Restore-TestEnvironment -TestEnvironment $script:testEnvironment +} -# Invoke-TestSetup +Invoke-TestSetup -# try -# { -# InModuleScope $script:dscResourceName { +try +{ + InModuleScope $script:dscResourceName { -# $testVMName = 'UnitTestVM' -# $testHardDiskPath = 'TestDrive:\{0}.vhdx' -f $testVMName + $testVMName = 'UnitTestVM' + $testHardDiskPath = 'TestDrive:\{0}.vhdx' -f $testVMName -# Describe 'DSC_VMHardDiskDrive\Get-TargetResource' { + Describe 'DSC_VMHardDiskDrive\Get-TargetResource' { -# $stubHardDiskDrive = [PSCustomObject] @{ -# VMName = $testVMName -# Path = $testHardDiskPath -# ControllerLocation = 0 -# ControllerNumber = 0 -# ControllerType = 'SCSI' -# } + $stubHardDiskDrive = [PSCustomObject] @{ + VMName = $testVMName + Path = $testHardDiskPath + ControllerLocation = 0 + ControllerNumber = 0 + ControllerType = 'SCSI' + } -# # Guard mocks -# Mock -CommandName Assert-Module + # Guard mocks + Mock -CommandName Assert-Module -# It 'Should return a [System.Collections.Hashtable] object type' { -# Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } + It 'Should return a [System.Collections.Hashtable] object type' { + Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } -# $result = Get-TargetResource -VMName $testVMName -Path $testhardDiskPath + $result = Get-TargetResource -VMName $testVMName -Path $testhardDiskPath -# $result -is [System.Collections.Hashtable] | Should -Be $true -# } + $result -is [System.Collections.Hashtable] | Should -Be $true + } -# It 'Should return "Present" when hard disk is attached' { -# Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } + It 'Should return "Present" when hard disk is attached' { + Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } -# $result = Get-TargetResource -VMName $testVMName -Path $testhardDiskPath + $result = Get-TargetResource -VMName $testVMName -Path $testhardDiskPath -# $result.Ensure | Should -Be 'Present' -# } + $result.Ensure | Should -Be 'Present' + } -# It 'Should return "Absent" when hard disk is not attached' { -# Mock -CommandName Get-VMHardDiskDrive + It 'Should return "Absent" when hard disk is not attached' { + Mock -CommandName Get-VMHardDiskDrive -# $result = Get-TargetResource -VMName $testVMName -Path $testhardDiskPath + $result = Get-TargetResource -VMName $testVMName -Path $testhardDiskPath -# $result.Ensure | Should -Be 'Absent' -# } + $result.Ensure | Should -Be 'Absent' + } -# It 'Should assert Hyper-V module is installed' { -# Mock -CommandName Assert-Module -# Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } + It 'Should assert Hyper-V module is installed' { + Mock -CommandName Assert-Module + Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } -# $null = Get-TargetResource -VMName $testVMName -Path $testhardDiskPath + $null = Get-TargetResource -VMName $testVMName -Path $testhardDiskPath -# Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It -# } -# } # descrive Get-TargetResource + Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It + } + } # descrive Get-TargetResource -# Describe 'DSC_VMHardDiskDrive\Test-TargetResource' { + Describe 'DSC_VMHardDiskDrive\Test-TargetResource' { -# # Guard mocks -# Mock -CommandName Assert-Module + # Guard mocks + Mock -CommandName Assert-Module -# $stubTargetResource = @{ -# VMName = $testVMName -# Path = $testHardDiskPath -# ControllerType = 'SCSI' -# ControllerNumber = 0 -# ControllerLocation = 0 -# Ensure = 'Present' -# } + $stubTargetResource = @{ + VMName = $testVMName + Path = $testHardDiskPath + ControllerType = 'SCSI' + ControllerNumber = 0 + ControllerLocation = 0 + Ensure = 'Present' + } -# It 'Should return a [System.Boolean] object type' { -# Mock -CommandName Get-TargetResource { return $stubTargetResource } + It 'Should return a [System.Boolean] object type' { + Mock -CommandName Get-TargetResource { return $stubTargetResource } -# $result = Test-TargetResource -VMName $testVMName -Path $testHardDiskPath + $result = Test-TargetResource -VMName $testVMName -Path $testHardDiskPath -# $result -is [System.Boolean] | Should -Be $true -# } + $result -is [System.Boolean] | Should -Be $true + } -# $parameterNames = @( -# 'ControllerNumber', -# 'ControllerLocation' -# ) + $parameterNames = @( + 'ControllerNumber', + 'ControllerLocation' + ) -# foreach ($parameterName in $parameterNames) -# { -# $parameterValue = $stubTargetResource[$parameterName] -# $testTargetResourceParams = @{ -# VMName = $testVMName -# Path = $testHardDiskPath -# } + foreach ($parameterName in $parameterNames) + { + $parameterValue = $stubTargetResource[$parameterName] + $testTargetResourceParams = @{ + VMName = $testVMName + Path = $testHardDiskPath + } -# It "Should pass when parameter '$parameterName' is correct" { -# # Pass value verbatim so it should always pass first -# $testTargetResourceParams[$parameterName] = $parameterValue + It "Should pass when parameter '$parameterName' is correct" { + # Pass value verbatim so it should always pass first + $testTargetResourceParams[$parameterName] = $parameterValue -# $result = Test-TargetResource @testTargetResourceParams + $result = Test-TargetResource @testTargetResourceParams -# $result | Should -Be $true -# } + $result | Should -Be $true + } -# It "Should fail when parameter '$parameterName' is incorrect" { -# # Add one to cause a test failure -# $testTargetResourceParams[$parameterName] = $parameterValue + 1 + It "Should fail when parameter '$parameterName' is incorrect" { + # Add one to cause a test failure + $testTargetResourceParams[$parameterName] = $parameterValue + 1 -# $result = Test-TargetResource @testTargetResourceParams + $result = Test-TargetResource @testTargetResourceParams -# $result | Should -Be $false -# } -# } + $result | Should -Be $false + } + } -# It "Should pass when parameter 'ControllerType' is correct" { -# $testTargetResourceParams = @{ -# VMName = $testVMName -# Path = $testHardDiskPath -# ControllerType = $stubTargetResource['ControllerType'] -# } + It "Should pass when parameter 'ControllerType' is correct" { + $testTargetResourceParams = @{ + VMName = $testVMName + Path = $testHardDiskPath + ControllerType = $stubTargetResource['ControllerType'] + } -# $result = Test-TargetResource @testTargetResourceParams + $result = Test-TargetResource @testTargetResourceParams -# $result | Should -Be $true -# } + $result | Should -Be $true + } -# It "Should fail when parameter 'ControllerType' is incorrect" { -# $testTargetResourceParams = @{ -# VMName = $testVMName -# Path = $testHardDiskPath -# ControllerType = 'IDE' -# } + It "Should fail when parameter 'ControllerType' is incorrect" { + $testTargetResourceParams = @{ + VMName = $testVMName + Path = $testHardDiskPath + ControllerType = 'IDE' + } -# $result = Test-TargetResource @testTargetResourceParams + $result = Test-TargetResource @testTargetResourceParams -# $result | Should -Be $false -# } + $result | Should -Be $false + } -# It "Should pass when parameter 'Ensure' is correct" { -# $testTargetResourceParams = @{ -# VMName = $testVMName -# Path = $testHardDiskPath -# Ensure = $stubTargetResource['Ensure'] -# } + It "Should pass when parameter 'Ensure' is correct" { + $testTargetResourceParams = @{ + VMName = $testVMName + Path = $testHardDiskPath + Ensure = $stubTargetResource['Ensure'] + } -# $result = Test-TargetResource @testTargetResourceParams + $result = Test-TargetResource @testTargetResourceParams -# $result | Should -Be $true -# } - -# It "Should fail when parameter 'Ensure' is incorrect" { -# $testTargetResourceParams = @{ -# VMName = $testVMName -# Path = $testHardDiskPath -# Ensure = 'Absent' -# } - -# $result = Test-TargetResource @testTargetResourceParams - -# $result | Should -Be $false -# } - -# It 'Should throw when IDE controller number 2 is specified' { -# $testTargetResourceParams = @{ -# VMName = $testVMName -# Path = $testHardDiskPath -# ControllerType = 'IDE' -# ControllerNumber = 2 -# } - -# { Test-TargetResource @testTargetResourceParams } | Should -Throw 'not valid' -# } - -# It 'Should throw when IDE controller location 2 is specified' { -# $testTargetResourceParams = @{ -# VMName = $testVMName -# Path = $testHardDiskPath -# ControllerType = 'IDE' -# ControllerLocation = 2 -# } - -# { Test-TargetResource @testTargetResourceParams } | Should -Throw 'not valid' -# } -# } # describe Test-TargetResource - -# Describe 'DSC_VMHardDiskDrive\Set-TargetResource' { -# # Guard mocks -# Mock -CommandName Assert-Module -# Mock -CommandName Get-VMHardDiskDrive -# Mock -CommandName Set-VMHardDiskDrive -# Mock -CommandName Add-VMHardDiskDrive -# Mock -CommandName Remove-VMHardDiskDrive - -# <# -# Create a mock of a the class HardDiskDrive to support piping to -# the cmdlet Set-VMHardDiskDrive. -# #> -# $stubHardDiskDrive = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() -# $stubHardDiskDrive.CimSession = New-MockObject -Type CimSession -# $stubHardDiskDrive.VMName = $testVMName -# $stubHardDiskDrive.Path = $testHardDiskPath -# $stubHardDiskDrive.ControllerLocation = 0 -# $stubHardDiskDrive.ControllerNumber = 0 -# $stubHardDiskDrive.ControllerType = 'SCSI' - -# It 'Should assert Hyper-V module is installed' { -# Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } - -# $null = Set-TargetResource -VMName $testVMName -Path $testHardDiskPath - -# Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It -# } - -# It 'Should update existing hard disk' { -# Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } - -# $null = Set-TargetResource -VMName $testVMName -Path $testHardDiskPath - -# Assert-MockCalled -CommandName Set-VMHardDiskDrive -Scope It -# } - -# It 'Should add hard disk when is not attached' { -# Mock -CommandName Get-VMHardDiskDrive -# Mock -CommandName Get-VMHardDiskDrive -ParameterFilter { $PSBoundParameters.ContainsKey('ControllerType') } - -# $null = Set-TargetResource -VMName $testVMName -Path $testHardDiskPath - -# Assert-MockCalled -CommandName Add-VMHardDiskDrive -Scope It -# } - -# It 'Should throw when an existing disk is attached to controller/location' { -# Mock -CommandName Get-VMHardDiskDrive -# Mock -CommandName Get-VMHardDiskDrive -ParameterFilter { $PSBoundParameters.ContainsKey('ControllerType') } { return $stubHardDiskDrive } - -# { Set-TargetResource -VMName $testVMName -Path $testHardDiskPath } | Should -Throw 'disk present' -# } - -# It 'Should remove attached hard disk when Ensure is "Absent"' { -# Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } - -# $null = Set-TargetResource -VMName $testVMName -Path $testHardDiskPath -Ensure 'Absent' - -# Assert-MockCalled -CommandName Remove-VMHardDiskDrive -Scope It -# } -# } # describe Set-TargetResource -# } # InModuleScope -# } -# finally -# { -# Invoke-TestCleanup -# } + $result | Should -Be $true + } + + It "Should fail when parameter 'Ensure' is incorrect" { + $testTargetResourceParams = @{ + VMName = $testVMName + Path = $testHardDiskPath + Ensure = 'Absent' + } + + $result = Test-TargetResource @testTargetResourceParams + + $result | Should -Be $false + } + + It 'Should throw when IDE controller number 2 is specified' { + $testTargetResourceParams = @{ + VMName = $testVMName + Path = $testHardDiskPath + ControllerType = 'IDE' + ControllerNumber = 2 + } + + { Test-TargetResource @testTargetResourceParams } | Should -Throw 'not valid' + } + + It 'Should throw when IDE controller location 2 is specified' { + $testTargetResourceParams = @{ + VMName = $testVMName + Path = $testHardDiskPath + ControllerType = 'IDE' + ControllerLocation = 2 + } + + { Test-TargetResource @testTargetResourceParams } | Should -Throw 'not valid' + } + } # describe Test-TargetResource + + Describe 'DSC_VMHardDiskDrive\Set-TargetResource' { + # Guard mocks + Mock -CommandName Assert-Module + Mock -CommandName Get-VMHardDiskDrive + Mock -CommandName Set-VMHardDiskDrive + Mock -CommandName Add-VMHardDiskDrive + Mock -CommandName Remove-VMHardDiskDrive + + <# + Create a mock of a the class HardDiskDrive to support piping to + the cmdlet Set-VMHardDiskDrive. + #> + $stubHardDiskDrive = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() + $stubHardDiskDrive.CimSession = New-MockObject -Type CimSession + $stubHardDiskDrive.VMName = $testVMName + $stubHardDiskDrive.Path = $testHardDiskPath + $stubHardDiskDrive.ControllerLocation = 0 + $stubHardDiskDrive.ControllerNumber = 0 + $stubHardDiskDrive.ControllerType = 'SCSI' + + It 'Should assert Hyper-V module is installed' { + Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } + + $null = Set-TargetResource -VMName $testVMName -Path $testHardDiskPath + + Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It + } + + It 'Should update existing hard disk' { + Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } + + $null = Set-TargetResource -VMName $testVMName -Path $testHardDiskPath + + Assert-MockCalled -CommandName Set-VMHardDiskDrive -Scope It + } + + It 'Should add hard disk when is not attached' { + Mock -CommandName Get-VMHardDiskDrive + Mock -CommandName Get-VMHardDiskDrive -ParameterFilter { $PSBoundParameters.ContainsKey('ControllerType') } + + $null = Set-TargetResource -VMName $testVMName -Path $testHardDiskPath + + Assert-MockCalled -CommandName Add-VMHardDiskDrive -Scope It + } + + It 'Should throw when an existing disk is attached to controller/location' { + Mock -CommandName Get-VMHardDiskDrive + Mock -CommandName Get-VMHardDiskDrive -ParameterFilter { $PSBoundParameters.ContainsKey('ControllerType') } { return $stubHardDiskDrive } + + { Set-TargetResource -VMName $testVMName -Path $testHardDiskPath } | Should -Throw 'disk present' + } + + It 'Should remove attached hard disk when Ensure is "Absent"' { + Mock -CommandName Get-VMHardDiskDrive { return $stubHardDiskDrive } + + $null = Set-TargetResource -VMName $testVMName -Path $testHardDiskPath -Ensure 'Absent' + + Assert-MockCalled -CommandName Remove-VMHardDiskDrive -Scope It + } + } # describe Set-TargetResource + } # InModuleScope +} +finally +{ + Invoke-TestCleanup +} diff --git a/tests/Unit/DSC_VMHost.Tests.ps1 b/tests/Unit/DSC_VMHost.Tests.ps1 index d8099bb..a53fef9 100644 --- a/tests/Unit/DSC_VMHost.Tests.ps1 +++ b/tests/Unit/DSC_VMHost.Tests.ps1 @@ -1,361 +1,361 @@ -# $script:dscModuleName = 'HyperVDsc' -# $script:dscResourceName = 'DSC_VMHost' - -# function Invoke-TestSetup -# { -# try -# { -# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' -# } -# catch [System.IO.FileNotFoundException] -# { -# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' -# } - -# $script:testEnvironment = Initialize-TestEnvironment ` -# -DSCModuleName $script:dscModuleName ` -# -DSCResourceName $script:dscResourceName ` -# -ResourceType 'Mof' ` -# -TestType 'Unit' - -# # Import the stub functions. -# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -# } - -# function Invoke-TestCleanup -# { -# Restore-TestEnvironment -TestEnvironment $script:testEnvironment -# } - -# Invoke-TestSetup - -# try -# { -# InModuleScope $script:dscResourceName { - -# $testVMName = 'UnitTestVM' - -# Describe 'DSC_VMHost\Get-TargetResource' { -# $fakeVMHost = @{ -# ResourceMeteringSaveInterval = 60 -# } - -# It 'Should return a [System.Collections.Hashtable] object type' { -# Mock -CommandName Assert-Module -# Mock -CommandName Get-VMHost { return $fakeVMHost } - -# $result = Get-TargetResource -IsSingleInstance 'Yes' - -# $result -is [System.Collections.Hashtable] | Should -Be $true -# } - -# It 'Should assert Hyper-V module is installed' { -# Mock -CommandName Assert-Module -# Mock -CommandName Get-VMHost { return $fakeVMHost } - -# $result = Get-TargetResource -IsSingleInstance 'Yes' - -# Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It -# } - -# } # describe Get-TargetResource - -# Describe 'DSC_VMHost\Test-TargetResource' { - -# # Guard mocks -# Mock -CommandName Assert-Module - -# $fakeTargetResource = @{ -# IsSingleInstance = 'Yes' -# EnableEnhancedSessionMode = $true -# FibreChannelWwnn = 'C003FF0000FFFF00' -# FibreChannelWwpnMaximum = 'C003FFFBEAE1FFFF' -# FibreChannelWwpnMinimum = 'C003FFFBEAE10000' -# MacAddressMinimum = '00155D327500' -# MacAddressMaximum = '00155D3275FF' -# MaximumStorageMigrations = 2 -# MaximumVirtualMachineMigrations = 2 -# NumaSpanningEnabled = $true -# ResourceMeteringSaveIntervalMinute = 60 -# UseAnyNetworkForMigration = $false -# VirtualMachinePath ='C:\ProgramData\Microsoft\Windows\Hyper-V' -# VirtualMachineMigrationAuthenticationType = 'CredSSP' -# VirtualMachineMigrationPerformanceOption = 'TCPIP' -# VirtualHardDiskPath = 'C:\Users\Public\Documents\Hyper-V\Virtual Hard Disks' -# VirtualMachineMigrationEnabled = $true -# } - -# It 'Should return a [System.Boolean] object type' { -# Mock -CommandName Get-TargetResource { return $fakeTargetResource } - -# $testTargetResourceParams = @{ -# IsSingleInstance = 'Yes' -# EnableEnhancedSessionMode = $fakeTargetResource.EnableEnhancedSessionMode -# VirtualMachineMigrationEnabled = $fakeTargetResource.VirtualMachineMigrationEnabled -# } -# $result = Test-TargetResource @testTargetResourceParams - -# $result -is [System.Boolean] | Should -Be $true -# } - -# It 'Should assert Hyper-V module is installed' { -# Mock -CommandName Get-TargetResource { return $fakeTargetResource } - -# $testTargetResourceParams = @{ -# IsSingleInstance = 'Yes' -# EnableEnhancedSessionMode = $fakeTargetResource.EnableEnhancedSessionMode -# } -# $result = Test-TargetResource @testTargetResourceParams - -# Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It -# } - -# $parameterNames = @( -# 'EnableEnhancedSessionMode', -# 'FibreChannelWwnn', -# 'FibreChannelWwpnMaximum', -# 'FibreChannelWwpnMinimum', -# 'MacAddressMaximum', -# 'MacAddressMinimum', -# 'MaximumStorageMigrations', -# 'MaximumVirtualMachineMigrations', -# 'NumaSpanningEnabled', -# 'ResourceMeteringSaveIntervalMinute', -# 'UseAnyNetworkForMigration', -# 'VirtualHardDiskPath', -# 'VirtualMachinePath', -# 'VirtualMachineMigrationEnabled' -# ) - -# # Test each individual parameter value separately -# foreach ($parameterName in $parameterNames) -# { -# $parameterValue = $fakeTargetResource[$parameterName] -# $testTargetResourceParams = @{ -# IsSingleInstance = 'Yes' -# } - -# # Pass value verbatim so it should always pass first -# It "Should pass when parameter '$parameterName' is correct" { -# $testTargetResourceParams[$parameterName] = $parameterValue - -# $result = Test-TargetResource @testTargetResourceParams - -# $result | Should -Be $true -# } - -# if ($parameterValue -is [System.Boolean]) -# { -# # Invert parameter value to cause a test failure -# $testTargetResourceParams[$parameterName] = -not $parameterValue -# } -# elseif ($parameterValue -is [System.String]) -# { -# # Repeat string to cause a test failure -# $testTargetResourceParams[$parameterName] = "$parameterValue$parameterValue" -# } -# elseif ($parameterValue -is [System.Int32] -or $parameterValue -is [System.Int64]) -# { -# # Add one to cause a test failure -# $testTargetResourceParams[$parameterName] = $parameterValue + 1 -# } - -# It "Should fail when parameter '$parameterName' is incorrect" { -# $result = Test-TargetResource @testTargetResourceParams - -# $result | Should -Be $false -# } -# } - -# It "Should pass when parameter is correct" -TestCases @( -# @{ -# Parameter = 'VirtualMachineMigrationAuthenticationType' -# Value = $fakeTargetResource.VirtualMachineMigrationAuthenticationType -# Expected = $true -# } -# @{ -# Parameter = 'VirtualMachineMigrationPerformanceOption' -# Value = $fakeTargetResource.VirtualMachineMigrationPerformanceOption -# Expected = $true -# } -# @{ -# Parameter = 'VirtualMachineMigrationEnabled' -# Value = $fakeTargetResource.VirtualMachineMigrationEnabled -# Expected = $true -# } -# ) -Test { -# param -# ( -# [Parameter()] -# [System.String] -# $Parameter, - -# [Parameter()] -# [System.Object] -# $Value, - -# [Parameter()] -# [System.Boolean] -# $Expected -# ) - -# $testTargetResourceParams = @{ -# IsSingleInstance = 'Yes' -# $Parameter = $Value -# } - -# $result = Test-TargetResource @testTargetResourceParams | Should -Be $Expected -# } - -# It "Should fail when parameter is incorrect" -TestCases @( -# @{ -# Parameter = 'VirtualMachineMigrationAuthenticationType' -# Value = 'Kerberos' -# Expected = $false -# } -# @{ -# Parameter = 'VirtualMachineMigrationPerformanceOption' -# Value = 'Compression' -# Expected = $false -# } -# @{ -# Parameter = 'VirtualMachineMigrationEnabled' -# Value = $true -# Expected = $true -# } -# ) -Test { -# param -# ( -# [Parameter()] -# [System.String] -# $Parameter, - -# [Parameter()] -# [System.Object] -# $Value, - -# [Parameter()] -# [System.Boolean] -# $Expected -# ) - -# $testTargetResourceParams = @{ -# IsSingleInstance = 'Yes' -# $Parameter = $Value -# } - -# $result = Test-TargetResource @testTargetResourceParams | Should -Be $Expected -# } - -# } # describe Test-TargetResource - -# Describe 'DSC_VMHost\Set-TargetResource' { -# # Guard mocks -# Mock -CommandName Assert-Module -# Mock -CommandName Get-VMHost -# Mock -CommandName Set-VMHost -# Mock -CommandName Enable-VMMigration -# Mock -CommandName Disable-VMMigration - -# It 'Should assert Hyper-V module is installed' { -# $setTargetResourceParams = @{ -# IsSingleInstance = 'Yes' -# } - -# $result = Set-TargetResource @setTargetResourceParams - -# Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It -# } - -# It 'Should call "Set-VMHost" with [System.TimeSpan] object when "ResourceMeteringSaveIntervalMinute" specified' { -# $setTargetResourceParams = @{ -# IsSingleInstance = 'Yes' -# ResourceMeteringSaveIntervalMinute = 60 -# } - -# $result = Set-TargetResource @setTargetResourceParams - -# Assert-MockCalled -CommandName Set-VMHost -ParameterFilter { $ResourceMeteringSaveInterval -is [System.TimeSpan] } -# } - -# It 'Should call "Enable-VMMigration" when "VirtualMachineMigrationEnabled" is set to true and computer is domain joined' { -# Mock -CommandName 'Get-CimInstance' -MockWith { -# [pscustomobject] @{ -# PartOfDomain = $true -# } -# } - -# Mock -CommandName 'Write-Error' - -# $setTargetResourceParams = @{ -# IsSingleInstance = 'Yes' -# VirtualMachineMigrationEnabled = $true -# } - -# $result = Set-TargetResource @setTargetResourceParams -# Assert-MockCalled -CommandName Write-Error -Times 0 -Exactly -Scope it -# Assert-MockCalled -CommandName Enable-VMMigration -Times 1 -Exactly -Scope it -# Assert-MockCalled -CommandName Disable-VMMigration -Times 0 -Exactly -Scope it -# } - -# It 'Should not call "Enable-VMMigration" and should throw when "VirtualMachineMigrationEnabled" is set to true and computer is not domain joined' { -# Mock -CommandName 'Get-CimInstance' -MockWith { -# [pscustomobject] @{ -# PartOfDomain = $false -# } -# } - -# $setTargetResourceParams = @{ -# IsSingleInstance = 'Yes' -# VirtualMachineMigrationEnabled = $true -# } - -# { Set-TargetResource @setTargetResourceParams } | Should -Throw -# Assert-MockCalled -CommandName Enable-VMMigration -Times 0 -Exactly -Scope it -# Assert-MockCalled -CommandName Disable-VMMigration -Times 0 -Exactly -Scope it -# } - -# It 'Should call "Disable-VMMigration" when "VirtualMachineMigrationEnabled" is set to false' { -# $setTargetResourceParams = @{ -# IsSingleInstance = 'Yes' -# VirtualMachineMigrationEnabled = $false -# } - -# $result = Set-TargetResource @setTargetResourceParams -# Assert-MockCalled -CommandName Enable-VMMigration -Times 0 -Exactly -Scope it -# Assert-MockCalled -CommandName Disable-VMMigration -Times 1 -Exactly -Scope it -# } - -# It 'Should not call "Disable-VMMigration" or "Enable-VMMigration" when "VirtualMachineMigrationEnabled" is not set' { -# $setTargetResourceParams = @{ -# IsSingleInstance = 'Yes' -# } - -# $result = Set-TargetResource @setTargetResourceParams - -# Assert-MockCalled -CommandName Enable-VMMigration -Times 0 -Exactly -Scope it -# Assert-MockCalled -CommandName Disable-VMMigration -Times 0 -Exactly -Scope it -# } - -# It 'Should not call "Set-VMHost" when only "VirtualMachineMigrationEnabled" is set' { -# $setTargetResourceParams = @{ -# IsSingleInstance = 'Yes' -# VirtualMachineMigrationEnabled = $false -# Verbose = $true -# } - -# $result = Set-TargetResource @setTargetResourceParams - -# Assert-MockCalled -CommandName Enable-VMMigration -Times 0 -Exactly -Scope it -# Assert-MockCalled -CommandName Disable-VMMigration -Times 1 -Exactly -Scope it -# Assert-MockCalled -CommandName Set-VMHost -Times 0 -Exactly -Scope it -# } - -# } # describe Set-TargetResource - -# } # InModuleScope -# } -# finally -# { -# Invoke-TestCleanup -# } +$script:dscModuleName = 'HyperVDsc' +$script:dscResourceName = 'DSC_VMHost' + +function Invoke-TestSetup +{ + try + { + Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + } + + $script:testEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:dscModuleName ` + -DSCResourceName $script:dscResourceName ` + -ResourceType 'Mof' ` + -TestType 'Unit' + + # Import the stub functions. + Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +} + +function Invoke-TestCleanup +{ + Restore-TestEnvironment -TestEnvironment $script:testEnvironment +} + +Invoke-TestSetup + +try +{ + InModuleScope $script:dscResourceName { + + $testVMName = 'UnitTestVM' + + Describe 'DSC_VMHost\Get-TargetResource' { + $fakeVMHost = @{ + ResourceMeteringSaveInterval = 60 + } + + It 'Should return a [System.Collections.Hashtable] object type' { + Mock -CommandName Assert-Module + Mock -CommandName Get-VMHost { return $fakeVMHost } + + $result = Get-TargetResource -IsSingleInstance 'Yes' + + $result -is [System.Collections.Hashtable] | Should -Be $true + } + + It 'Should assert Hyper-V module is installed' { + Mock -CommandName Assert-Module + Mock -CommandName Get-VMHost { return $fakeVMHost } + + $result = Get-TargetResource -IsSingleInstance 'Yes' + + Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It + } + + } # describe Get-TargetResource + + Describe 'DSC_VMHost\Test-TargetResource' { + + # Guard mocks + Mock -CommandName Assert-Module + + $fakeTargetResource = @{ + IsSingleInstance = 'Yes' + EnableEnhancedSessionMode = $true + FibreChannelWwnn = 'C003FF0000FFFF00' + FibreChannelWwpnMaximum = 'C003FFFBEAE1FFFF' + FibreChannelWwpnMinimum = 'C003FFFBEAE10000' + MacAddressMinimum = '00155D327500' + MacAddressMaximum = '00155D3275FF' + MaximumStorageMigrations = 2 + MaximumVirtualMachineMigrations = 2 + NumaSpanningEnabled = $true + ResourceMeteringSaveIntervalMinute = 60 + UseAnyNetworkForMigration = $false + VirtualMachinePath ='C:\ProgramData\Microsoft\Windows\Hyper-V' + VirtualMachineMigrationAuthenticationType = 'CredSSP' + VirtualMachineMigrationPerformanceOption = 'TCPIP' + VirtualHardDiskPath = 'C:\Users\Public\Documents\Hyper-V\Virtual Hard Disks' + VirtualMachineMigrationEnabled = $true + } + + It 'Should return a [System.Boolean] object type' { + Mock -CommandName Get-TargetResource { return $fakeTargetResource } + + $testTargetResourceParams = @{ + IsSingleInstance = 'Yes' + EnableEnhancedSessionMode = $fakeTargetResource.EnableEnhancedSessionMode + VirtualMachineMigrationEnabled = $fakeTargetResource.VirtualMachineMigrationEnabled + } + $result = Test-TargetResource @testTargetResourceParams + + $result -is [System.Boolean] | Should -Be $true + } + + It 'Should assert Hyper-V module is installed' { + Mock -CommandName Get-TargetResource { return $fakeTargetResource } + + $testTargetResourceParams = @{ + IsSingleInstance = 'Yes' + EnableEnhancedSessionMode = $fakeTargetResource.EnableEnhancedSessionMode + } + $result = Test-TargetResource @testTargetResourceParams + + Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It + } + + $parameterNames = @( + 'EnableEnhancedSessionMode', + 'FibreChannelWwnn', + 'FibreChannelWwpnMaximum', + 'FibreChannelWwpnMinimum', + 'MacAddressMaximum', + 'MacAddressMinimum', + 'MaximumStorageMigrations', + 'MaximumVirtualMachineMigrations', + 'NumaSpanningEnabled', + 'ResourceMeteringSaveIntervalMinute', + 'UseAnyNetworkForMigration', + 'VirtualHardDiskPath', + 'VirtualMachinePath', + 'VirtualMachineMigrationEnabled' + ) + + # Test each individual parameter value separately + foreach ($parameterName in $parameterNames) + { + $parameterValue = $fakeTargetResource[$parameterName] + $testTargetResourceParams = @{ + IsSingleInstance = 'Yes' + } + + # Pass value verbatim so it should always pass first + It "Should pass when parameter '$parameterName' is correct" { + $testTargetResourceParams[$parameterName] = $parameterValue + + $result = Test-TargetResource @testTargetResourceParams + + $result | Should -Be $true + } + + if ($parameterValue -is [System.Boolean]) + { + # Invert parameter value to cause a test failure + $testTargetResourceParams[$parameterName] = -not $parameterValue + } + elseif ($parameterValue -is [System.String]) + { + # Repeat string to cause a test failure + $testTargetResourceParams[$parameterName] = "$parameterValue$parameterValue" + } + elseif ($parameterValue -is [System.Int32] -or $parameterValue -is [System.Int64]) + { + # Add one to cause a test failure + $testTargetResourceParams[$parameterName] = $parameterValue + 1 + } + + It "Should fail when parameter '$parameterName' is incorrect" { + $result = Test-TargetResource @testTargetResourceParams + + $result | Should -Be $false + } + } + + It "Should pass when parameter is correct" -TestCases @( + @{ + Parameter = 'VirtualMachineMigrationAuthenticationType' + Value = $fakeTargetResource.VirtualMachineMigrationAuthenticationType + Expected = $true + } + @{ + Parameter = 'VirtualMachineMigrationPerformanceOption' + Value = $fakeTargetResource.VirtualMachineMigrationPerformanceOption + Expected = $true + } + @{ + Parameter = 'VirtualMachineMigrationEnabled' + Value = $fakeTargetResource.VirtualMachineMigrationEnabled + Expected = $true + } + ) -Test { + param + ( + [Parameter()] + [System.String] + $Parameter, + + [Parameter()] + [System.Object] + $Value, + + [Parameter()] + [System.Boolean] + $Expected + ) + + $testTargetResourceParams = @{ + IsSingleInstance = 'Yes' + $Parameter = $Value + } + + $result = Test-TargetResource @testTargetResourceParams | Should -Be $Expected + } + + It "Should fail when parameter is incorrect" -TestCases @( + @{ + Parameter = 'VirtualMachineMigrationAuthenticationType' + Value = 'Kerberos' + Expected = $false + } + @{ + Parameter = 'VirtualMachineMigrationPerformanceOption' + Value = 'Compression' + Expected = $false + } + @{ + Parameter = 'VirtualMachineMigrationEnabled' + Value = $true + Expected = $true + } + ) -Test { + param + ( + [Parameter()] + [System.String] + $Parameter, + + [Parameter()] + [System.Object] + $Value, + + [Parameter()] + [System.Boolean] + $Expected + ) + + $testTargetResourceParams = @{ + IsSingleInstance = 'Yes' + $Parameter = $Value + } + + $result = Test-TargetResource @testTargetResourceParams | Should -Be $Expected + } + + } # describe Test-TargetResource + + Describe 'DSC_VMHost\Set-TargetResource' { + # Guard mocks + Mock -CommandName Assert-Module + Mock -CommandName Get-VMHost + Mock -CommandName Set-VMHost + Mock -CommandName Enable-VMMigration + Mock -CommandName Disable-VMMigration + + It 'Should assert Hyper-V module is installed' { + $setTargetResourceParams = @{ + IsSingleInstance = 'Yes' + } + + $result = Set-TargetResource @setTargetResourceParams + + Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It + } + + It 'Should call "Set-VMHost" with [System.TimeSpan] object when "ResourceMeteringSaveIntervalMinute" specified' { + $setTargetResourceParams = @{ + IsSingleInstance = 'Yes' + ResourceMeteringSaveIntervalMinute = 60 + } + + $result = Set-TargetResource @setTargetResourceParams + + Assert-MockCalled -CommandName Set-VMHost -ParameterFilter { $ResourceMeteringSaveInterval -is [System.TimeSpan] } + } + + It 'Should call "Enable-VMMigration" when "VirtualMachineMigrationEnabled" is set to true and computer is domain joined' { + Mock -CommandName 'Get-CimInstance' -MockWith { + [pscustomobject] @{ + PartOfDomain = $true + } + } + + Mock -CommandName 'Write-Error' + + $setTargetResourceParams = @{ + IsSingleInstance = 'Yes' + VirtualMachineMigrationEnabled = $true + } + + $result = Set-TargetResource @setTargetResourceParams + Assert-MockCalled -CommandName Write-Error -Times 0 -Exactly -Scope it + Assert-MockCalled -CommandName Enable-VMMigration -Times 1 -Exactly -Scope it + Assert-MockCalled -CommandName Disable-VMMigration -Times 0 -Exactly -Scope it + } + + It 'Should not call "Enable-VMMigration" and should throw when "VirtualMachineMigrationEnabled" is set to true and computer is not domain joined' { + Mock -CommandName 'Get-CimInstance' -MockWith { + [pscustomobject] @{ + PartOfDomain = $false + } + } + + $setTargetResourceParams = @{ + IsSingleInstance = 'Yes' + VirtualMachineMigrationEnabled = $true + } + + { Set-TargetResource @setTargetResourceParams } | Should -Throw + Assert-MockCalled -CommandName Enable-VMMigration -Times 0 -Exactly -Scope it + Assert-MockCalled -CommandName Disable-VMMigration -Times 0 -Exactly -Scope it + } + + It 'Should call "Disable-VMMigration" when "VirtualMachineMigrationEnabled" is set to false' { + $setTargetResourceParams = @{ + IsSingleInstance = 'Yes' + VirtualMachineMigrationEnabled = $false + } + + $result = Set-TargetResource @setTargetResourceParams + Assert-MockCalled -CommandName Enable-VMMigration -Times 0 -Exactly -Scope it + Assert-MockCalled -CommandName Disable-VMMigration -Times 1 -Exactly -Scope it + } + + It 'Should not call "Disable-VMMigration" or "Enable-VMMigration" when "VirtualMachineMigrationEnabled" is not set' { + $setTargetResourceParams = @{ + IsSingleInstance = 'Yes' + } + + $result = Set-TargetResource @setTargetResourceParams + + Assert-MockCalled -CommandName Enable-VMMigration -Times 0 -Exactly -Scope it + Assert-MockCalled -CommandName Disable-VMMigration -Times 0 -Exactly -Scope it + } + + It 'Should not call "Set-VMHost" when only "VirtualMachineMigrationEnabled" is set' { + $setTargetResourceParams = @{ + IsSingleInstance = 'Yes' + VirtualMachineMigrationEnabled = $false + Verbose = $true + } + + $result = Set-TargetResource @setTargetResourceParams + + Assert-MockCalled -CommandName Enable-VMMigration -Times 0 -Exactly -Scope it + Assert-MockCalled -CommandName Disable-VMMigration -Times 1 -Exactly -Scope it + Assert-MockCalled -CommandName Set-VMHost -Times 0 -Exactly -Scope it + } + + } # describe Set-TargetResource + + } # InModuleScope +} +finally +{ + Invoke-TestCleanup +} diff --git a/tests/Unit/DSC_VMHyperV.Tests.ps1 b/tests/Unit/DSC_VMHyperV.Tests.ps1 index a789c33..13097b0 100644 --- a/tests/Unit/DSC_VMHyperV.Tests.ps1 +++ b/tests/Unit/DSC_VMHyperV.Tests.ps1 @@ -1,964 +1,964 @@ -# $script:dscModuleName = 'HyperVDsc' -# $script:dscResourceName = 'DSC_VMHyperV' - -# function Invoke-TestSetup -# { -# try -# { -# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' -# } -# catch [System.IO.FileNotFoundException] -# { -# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' -# } - -# $script:testEnvironment = Initialize-TestEnvironment ` -# -DSCModuleName $script:dscModuleName ` -# -DSCResourceName $script:dscResourceName ` -# -ResourceType 'Mof' ` -# -TestType 'Unit' - -# # Import the stub functions. -# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -# } - -# function Invoke-TestCleanup -# { -# Restore-TestEnvironment -TestEnvironment $script:testEnvironment -# } - -# Invoke-TestSetup - -# try -# { -# InModuleScope $script:dscResourceName { -# Describe 'xVMHyper-V' { -# $null = New-Item -Path 'TestDrive:\TestVM.vhdx' -ItemType File -# $null = New-Item -Path 'TestDrive:\TestVM.vhd' -ItemType File - -# $stubVhdxDisk = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() -# $stubVhdxDisk.Path = 'TestDrive:\TestVM.vhdx' - -# $stubVhdDisk = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() -# $stubVhdDisk.Path = 'TestDrive:\TestVM.vhd' - -# $studVhdxDiskSnapshot = New-Item -Path "TestDrive:\TestVM_D0145678-1576-4435-AB18-9F000C1C17D0.avhdx" -ItemType File -# $StubVMConfig = New-Item -Path 'TestDrive:\TestVM.xml' -ItemType File - -# # Mock the class VMNetworkAdapter to support piping to cmdlet Connect-VMNetworkAdapter -# $stubNIC1 = [Microsoft.HyperV.PowerShell.VMNetworkAdapter]::CreateTypeInstance() -# $stubNIC1.SwitchName = 'Test Switch 1' -# $stubNIC1.MacAddress = 'AA-BB-CC-DD-EE-FF' -# $stubNIC1.IpAddresses = @('192.168.0.1', '10.0.0.1') - -# # Mock the class VMNetworkAdapter to support piping to cmdlet Connect-VMNetworkAdapter -# $stubNIC2 = [Microsoft.HyperV.PowerShell.VMNetworkAdapter]::CreateTypeInstance() -# $stubNIC2.SwitchName = 'Test Switch 2' -# $stubNIC2.MacAddress = 'AA-BB-CC-DD-EE-FE' -# $stubNIC2.IpAddresses = @('192.168.1.1') - -# $mockVmGuid = [System.Guid]::NewGuid().ToString() - -# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'RunningVM' } -MockWith { -# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() -# $stubVM.Name = 'RunningVM' -# $stubVM.HardDrives = @( -# $stubVhdxDisk, -# $stubVhdDisk -# ) -# $stubVM.Path = $StubVMConfig.FullPath -# $stubVM.Generation = 1 -# $stubVM.MemoryStartup = 512MB -# $stubVM.MemoryMinimum = 128MB -# $stubVM.MemoryMaximum = 4096MB -# $stubVM.ProcessorCount = 1 -# $stubVM.ID = $mockVmGuid -# $stubVM.CPUUsage = 10 -# $stubVM.MemoryAssigned = 512MB -# $stubVM.Uptime = New-TimeSpan -Hours 12 -# $stubVM.CreationTime = (Get-Date).AddHours(-12) -# $stubVM.DynamicMemoryEnabled = $true -# $stubVM.Notes = '' -# $stubVM.State = 'Running' -# $stubVM.NetworkAdapters = @( -# $stubNIC1, -# $stubNIC2 -# ) - -# return $stubVM -# } - -# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'StoppedVM' } -MockWith { -# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() -# $stubVM.Name = 'StoppedVM' -# $stubVM.HardDrives = @( -# $stubVhdxDisk, -# $stubVhdDisk -# ) -# $stubVM.Path = $StubVMConfig.FullPath -# $stubVM.Generation = 1 -# $stubVM.MemoryStartup = 512MB -# $stubVM.MemoryMinimum = 128MB -# $stubVM.MemoryMaximum = 4096MB -# $stubVM.ProcessorCount = 1 -# $stubVM.ID = $mockVmGuid -# $stubVM.CPUUsage = 10 -# $stubVM.MemoryAssigned = 512MB -# $stubVM.Uptime = New-TimeSpan -Hours 12 -# $stubVM.CreationTime = (Get-Date).AddHours(-12) -# $stubVM.DynamicMemoryEnabled = $true -# $stubVM.Notes = '' -# $stubVM.State = 'Off' -# $stubVM.NetworkAdapters = @( -# $stubNIC1, -# $stubNIC2 -# ) - -# return $stubVM -# } - -# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'PausedVM' } -MockWith { -# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() -# $stubVM.Name = 'PausedVM' -# $stubVM.HardDrives = @( -# $stubVhdxDisk, -# $stubVhdDisk -# ) -# $stubVM.Path = $StubVMConfig.FullPath -# $stubVM.Generation = 1 -# $stubVM.MemoryStartup = 512MB -# $stubVM.MemoryMinimum = 128MB -# $stubVM.MemoryMaximum = 4096MB -# $stubVM.ProcessorCount = 1 -# $stubVM.ID = $mockVmGuid -# $stubVM.CPUUsage = 10 -# $stubVM.MemoryAssigned = 512MB -# $stubVM.Uptime = New-TimeSpan -Hours 12 -# $stubVM.CreationTime = (Get-Date).AddHours(-12) -# $stubVM.DynamicMemoryEnabled = $true -# $stubVM.Notes = '' -# $stubVM.State = 'Paused' -# $stubVM.NetworkAdapters = @( -# $stubNIC1, -# $stubNIC2 -# ) - -# return $stubVM -# } - -# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'NonexistentVM' } -MockWith { -# Write-Error 'VM not found.' -# } - -# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'DuplicateVM' } -MockWith { -# $stubVM1 = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() -# $stubVM1.Name = 'DuplicateVM' -# $stubVM1.HardDrives = @( -# $stubVhdxDisk, -# $stubVhdDisk -# ) -# $stubVM1.Path = $StubVMConfig.FullPath -# $stubVM1.Generation = 1 -# $stubVM1.MemoryStartup = 512MB -# $stubVM1.MemoryMinimum = 128MB -# $stubVM1.MemoryMaximum = 4096MB -# $stubVM1.ProcessorCount = 1 -# $stubVM1.ID = $mockVmGuid -# $stubVM1.CPUUsage = 10 -# $stubVM1.MemoryAssigned = 512MB -# $stubVM1.Uptime = New-TimeSpan -Hours 12 -# $stubVM1.CreationTime = (Get-Date).AddHours(-12) -# $stubVM1.DynamicMemoryEnabled = $true -# $stubVM1.Notes = '' -# $stubVM1.State = 'Off' -# $stubVM1.NetworkAdapters = @( -# $stubNIC1, -# $stubNIC2 -# ) - -# $stubVM2 = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() -# $stubVM2.Name = 'DuplicateVM' -# $stubVM2.HardDrives = @( -# $stubVhdxDisk, -# $stubVhdDisk -# ) -# $stubVM2.Path = $StubVMConfig.FullPath -# $stubVM2.Generation = 1 -# $stubVM2.MemoryStartup = 512MB -# $stubVM2.MemoryMinimum = 128MB -# $stubVM2.MemoryMaximum = 4096MB -# $stubVM2.ProcessorCount = 1 -# $stubVM2.ID = $mockVmGuid -# $stubVM2.CPUUsage = 10 -# $stubVM2.MemoryAssigned = 512MB -# $stubVM2.Uptime = New-TimeSpan -Hours 12 -# $stubVM2.CreationTime = (Get-Date).AddHours(-12) -# $stubVM2.DynamicMemoryEnabled = $true -# $stubVM2.Notes = '' -# $stubVM2.State = 'Off' -# $stubVM2.NetworkAdapters = @( -# $stubNIC1, -# $stubNIC2 -# ) - -# return @( -# $stubVM1, -# $stubVM2 -# ) -# } - -# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'Generation1Vhd' } -MockWith { -# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() -# $stubVM.Name = 'Generation1Vhd' -# $stubVM.HardDrives = @( -# $stubVhdDisk -# ) -# $stubVM.Path = $StubVMConfig.FullPath -# $stubVM.Generation = 1 -# $stubVM.MemoryStartup = 512MB -# $stubVM.MemoryMinimum = 128MB -# $stubVM.MemoryMaximum = 4096MB -# $stubVM.ProcessorCount = 1 -# $stubVM.ID = $mockVmGuid -# $stubVM.CPUUsage = 10 -# $stubVM.MemoryAssigned = 512MB -# $stubVM.Uptime = New-TimeSpan -Hours 12 -# $stubVM.CreationTime = (Get-Date).AddHours(-12) -# $stubVM.DynamicMemoryEnabled = $true -# $stubVM.Notes = '' -# $stubVM.State = 'Running' -# $stubVM.NetworkAdapters = @( -# $stubNIC1, -# $stubNIC2 -# ) - -# return $stubVM -# } - -# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'Generation2VM' } -MockWith { -# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() -# $stubVM.Name = 'Generation2VM' -# $stubVM.HardDrives = @( -# $stubVhdxDisk -# ) -# $stubVM.Path = $StubVMConfig.FullPath -# $stubVM.Generation = 2 -# $stubVM.MemoryStartup = 512MB -# $stubVM.MemoryMinimum = 128MB -# $stubVM.MemoryMaximum = 4096MB -# $stubVM.ProcessorCount = 1 -# $stubVM.ID = $mockVmGuid -# $stubVM.CPUUsage = 10 -# $stubVM.MemoryAssigned = 512MB -# $stubVM.Uptime = New-TimeSpan -Hours 12 -# $stubVM.CreationTime = (Get-Date).AddHours(-12) -# $stubVM.DynamicMemoryEnabled = $true -# $stubVM.Notes = '' -# $stubVM.State = 'Running' -# $stubVM.NetworkAdapters = @( -# $stubNIC1, -# $stubNIC2 -# ) - -# return $stubVM -# } - -# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'VMWithAutomaticCheckpoints' } -MockWith { -# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() -# $stubVM.Name = 'VMWithAutomaticCheckpoints' -# $stubVM.HardDrives = @( -# $stubVhdxDisk -# ) -# $stubVM.Path = $StubVMConfig.FullPath -# $stubVM.Generation = 2 -# $stubVM.MemoryStartup = 512MB -# $stubVM.MemoryMinimum = 128MB -# $stubVM.MemoryMaximum = 4096MB -# $stubVM.ProcessorCount = 1 -# $stubVM.ID = $mockVmGuid -# $stubVM.CPUUsage = 10 -# $stubVM.MemoryAssigned = 512MB -# $stubVM.Uptime = New-TimeSpan -Hours 12 -# $stubVM.CreationTime = (Get-Date).AddHours(-12) -# $stubVM.DynamicMemoryEnabled = $true -# $stubVM.Notes = '' -# $stubVM.State = 'Running' -# $stubVM.AutomaticCheckpointsEnabled = $true -# $stubVM.NetworkAdapters = @( -# $stubNIC1, -# $stubNIC2 -# ) - -# return $stubVM -# } - -# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'VMWithoutAutomaticCheckpoints' } -MockWith { -# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() -# $stubVM.Name = 'VMWithoutAutomaticCheckpoints' -# $stubVM.HardDrives = @( -# $stubVhdxDisk -# ) -# $stubVM.Path = $StubVMConfig.FullPath -# $stubVM.Generation = 2 -# $stubVM.MemoryStartup = 512MB -# $stubVM.MemoryMinimum = 128MB -# $stubVM.MemoryMaximum = 4096MB -# $stubVM.ProcessorCount = 1 -# $stubVM.ID = $mockVmGuid -# $stubVM.CPUUsage = 10 -# $stubVM.MemoryAssigned = 512MB -# $stubVM.Uptime = New-TimeSpan -Hours 12 -# $stubVM.CreationTime = (Get-Date).AddHours(-12) -# $stubVM.DynamicMemoryEnabled = $true -# $stubVM.Notes = '' -# $stubVM.State = 'Running' -# $stubVM.AutomaticCheckpointsEnabled = $false -# $stubVM.NetworkAdapters = @( -# $stubNIC1, -# $stubNIC2 -# ) - -# return $stubVM -# } - -# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'VMAutomaticCheckpointsUnsupported' } -MockWith { -# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() -# $stubVM.Name = 'VMAutomaticCheckpointsUnsupported' -# $stubVM.HardDrives = @( -# $stubVhdxDisk -# ) -# $stubVM.Path = $StubVMConfig.FullPath -# $stubVM.Generation = 2 -# $stubVM.MemoryStartup = 512MB -# $stubVM.MemoryMinimum = 128MB -# $stubVM.MemoryMaximum = 4096MB -# $stubVM.ProcessorCount = 1 -# $stubVM.ID = $mockVmGuid -# $stubVM.CPUUsage = 10 -# $stubVM.MemoryAssigned = 512MB -# $stubVM.Uptime = New-TimeSpan -Hours 12 -# $stubVM.CreationTime = (Get-Date).AddHours(-12) -# $stubVM.DynamicMemoryEnabled = $true -# $stubVM.Notes = '' -# $stubVM.State = 'Running' -# $stubVM.NetworkAdapters = @( -# $stubNIC1, -# $stubNIC2 -# ) - -# return $stubVM -# } - -# $stubGuestServiceInterfaceId = 'Microsoft:{0}\6C09BB55-D683-4DA0-8931-C9BF705F6480' -f $mockVmGuid - -# Mock -CommandName Get-VMIntegrationService -MockWith { -# $guestServiceInterface = [Microsoft.HyperV.PowerShell.VMIntegrationComponent]::CreateTypeInstance() -# $guestServiceInterface.Enabled = $false -# $guestServiceInterface.Id = $stubGuestServiceInterfaceId - -# return $guestServiceInterface -# } - -# Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } -MockWith { return $true } -# Mock -CommandName Get-VhdHierarchy -ParameterFilter { $VhdPath.EndsWith('.vhd') } -MockWith { -# # Return single Vhd chain for .vhds -# return @($stubVhdDisk.Path) -# } -# Mock -CommandName Get-VhdHierarchy -ParameterFilter { $VhdPath.EndsWith('.vhdx') } -MockWith { -# # Return snapshot hierarchy for .vhdxs -# return @($stubVhdxDiskSnapshot.FullName, $stubVhdxDisk.Path) -# } -# Context 'Validates Get-TargetResource Method' { - -# It 'Returns a hashtable' { -# $targetResource = Get-TargetResource -Name 'RunningVM' -VhdPath $stubVhdxDisk.Path -# $targetResource -is [System.Collections.Hashtable] | Should -Be $true -# } - -# It 'throws when multiple VMs are present' { -# { Get-TargetResource -Name 'DuplicateVM' -VhdPath $stubVhdxDisk.Path } | Should -Throw -# } - -# It 'Does not call Get-VMFirmware if a generation 1 VM' { -# Mock -CommandName Get-VMFirmware -MockWith { throw } -# $null = Get-TargetResource -Name 'RunningVM' -VhdPath $stubVhdxDisk.Path -# Assert-MockCalled -CommandName Get-VMFirmware -Scope It -Exactly 0 -# } - -# It 'Calls Get-VMFirmware if a generation 2 VM' { -# Mock -CommandName Get-VMFirmware -MockWith { return $true } -# $null = Get-TargetResource -Name 'Generation2VM' -VhdPath $stubVhdxDisk.Path -# Assert-MockCalled -CommandName Get-VMFirmware -Scope It -Exactly 1 -# } - -# It 'Hash table contains key EnableGuestService' { -# $targetResource = Get-TargetResource -Name 'RunningVM' -VhdPath $stubVhdxDisk.Path -# $targetResource.ContainsKey('EnableGuestService') | Should -Be $true -# } -# It 'Hash table contains key AutomaticCheckpointEnabled' { -# $targetResource = Get-TargetResource -Name 'VMWithAutomaticCheckpoints' -VhdPath $stubVhdxDisk.Path -# $targetResource.ContainsKey('AutomaticCheckpointsEnabled') | Should -Be $true -# } -# It 'throws when Hyper-V Tools are not installed' { -# # This test needs to be the last in the Context otherwise all subsequent Get-Module checks will fail -# Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } -# { Get-TargetResource -Name 'RunningVM' @testParams } | Should -Throw -# } -# } #end context Validates Get-TargetResource Method - -# Context 'Validates Test-TargetResource Method' { -# $testParams = @{ -# VhdPath = $stubVhdxDisk.Path -# } - -# It 'Returns a boolean' { -# $targetResource = Test-TargetResource -Name 'RunningVM' @testParams -# $targetResource -is [System.Boolean] | Should -Be $true -# } - -# It 'Returns $true when VM is present and "Ensure" = "Present"' { -# Test-TargetResource -Name 'RunningVM' @testParams | Should -Be $true -# } - -# It 'Returns $false when VM is not present and "Ensure" = "Present"' { -# Test-TargetResource -Name 'NonexistentVM' @testParams | Should -Be $false -# } - -# It 'Returns $true when VM is not present and "Ensure" = "Absent"' { -# Test-TargetResource -Name 'NonexistentVM' -Ensure Absent @testParams | Should -Be $true -# } - -# It 'Returns $false when VM is present and "Ensure" = "Absent"' { -# Test-TargetResource -Name 'RunningVM' -Ensure Absent @testParams | Should -Be $false -# } - -# It 'Returns $true when VM is in the "Running" state and no state is explicitly specified' { -# Test-TargetResource -Name 'RunningVM' @testParams | Should -Be $true -# } - -# It 'Returns $true when VM is in the "Stopped" state and no state is explicitly specified' { -# Test-TargetResource -Name 'StoppedVM' @testParams | Should -Be $true -# } - -# It 'Returns $true when VM is in the "Paused" state and no state is explicitly specified' { -# Test-TargetResource -Name 'PausedVM' @testParams | Should -Be $true -# } - -# It 'Returns $true when VM is in the "Running" state and requested "State" = "Running"' { -# Test-TargetResource -Name 'RunningVM' @testParams | Should -Be $true -# } - -# It 'Returns $true when VM is in the "Off" state and requested "State" = "Off"' { -# Test-TargetResource -Name 'StoppedVM' -State Off @testParams | Should -Be $true -# } - -# It 'Returns $true when VM is in the "Paused" state and requested "State" = Paused"' { -# Test-TargetResource -Name 'PausedVM' -State Paused @testParams | Should -Be $true -# } - -# It 'Returns $false when VM is in the "Running" state and requested "State" = "Off"' { -# Test-TargetResource -Name 'RunningVM' -State Off @testParams | Should -Be $false -# } - -# It 'Returns $false when VM is in the "Off" state and requested "State" = "Runnning"' { -# Test-TargetResource -Name 'StoppedVM' -State Running @testParams | Should -Be $false -# } - -# It 'Returns $true when VM .vhd file is specified with a generation 1 VM' { -# Test-TargetResource -Name 'Generation1Vhd' -VhdPath $stubVhdDisk.Path -Generation 1 -Verbose | Should -Be $true -# } - -# It 'Returns $true when VM .vhdx file is specified with a generation 1 VM' { -# Test-TargetResource -Name 'StoppedVM' -VhdPath $stubVhdxDisk.Path -Generation 1 | Should -Be $true -# } - -# It 'Returns $true when VM .vhdx file is specified with a generation 2 VM' { -# Mock -CommandName Test-VMSecureBoot -MockWith { return $true } -# Test-TargetResource -Name 'Generation2VM' -Generation 2 @testParams | Should -Be $true -# } - -# It 'throws when a VM .vhd file is specified with a generation 2 VM' { -# { Test-TargetResource -Name 'Gen2VM' -VhdPath $stubVhdDisk.Path -Generation 2 } | Should -Throw -# } - -# It 'Returns $true when multiple NICs are assigned in the correct order' { -# Test-TargetResource -Name 'RunningVM' @testParams -SwitchName @($stubNIC1.SwitchName, $stubNIC2.SwitchName) | Should -Be $true -# } - -# It 'Returns $false when multiple NICs are not assigned/assigned in the wrong order' { -# Test-TargetResource -Name 'RunningVM' @testParams -SwitchName @($stubNIC2.SwitchName, $stubNIC1.SwitchName) | Should -Be $false -# } - -# It 'Returns $true when multiple MAC addresses are assigned in the correct order' { -# Test-TargetResource -Name 'RunningVM' @testParams -MACAddress @($stubNIC1.MACAddress, $stubNIC2.MACAddress) | Should -Be $true -# } - -# It 'Returns $false when multiple MAC addresses not assigned/assigned in the wrong order' { -# Test-TargetResource -Name 'RunningVM' @testParams -MACAddress @($stubNIC1.MACAddress, $stubNIC2.MACAddress) | Should -Be $true -# } - -# It 'Returns $true regardless of "SecureBoot" setting on a generation 1 VM' { -# Test-TargetResource -Name 'RunningVM' -SecureBoot $true @testParams | Should -Be $true -# Test-TargetResource -Name 'RunningVM' -SecureBoot $false @testParams | Should -Be $true -# } - -# It 'Returns $true when SecureBoot is On and requested "SecureBoot" = "$true"' { -# Mock -CommandName Test-VMSecureBoot -MockWith { return $true } -# Test-TargetResource -Name 'Generation2VM' -Generation 2 @testParams | Should -Be $true -# } - -# It 'Returns $false when SecureBoot is On and requested "SecureBoot" = "$false"' { -# Mock -CommandName Test-VMSecureBoot -MockWith { return $true } -# Test-TargetResource -Name 'Generation2VM' -SecureBoot $false -Generation 2 @testParams | Should -Be $false -# } - -# It 'Returns $true when VM has snapshot chain' { -# Mock -CommandName Get-VhdHierarchy -MockWith { -# return @($studVhdxDiskSnapshot, $stubVhdxDisk) -# } -# Test-TargetResource -Name 'Generation2VM' -VhdPath $stubVhdxDisk.Path -Verbose | Should -Be $true -# } - -# It 'Returns $false when EnableGuestService is off and requested "EnableGuestService" = "$true"' { -# Test-TargetResource -Name 'RunningVM' -EnableGuestService $true @testParams | Should -Be $false -# } - -# It 'Returns $true when EnableGuestService is off and "EnableGuestService" is not requested"' { -# Test-TargetResource -Name 'RunningVM' @testParams | Should -Be $true -# } - -# Mock -CommandName Get-Command -ParameterFilter { $Name -eq 'Set-VM' -and $Module -eq 'Hyper-V' } -MockWith { -# [pscustomobject]@{ -# parameters = @{ -# # Does not contains parameter AutomaticCheckpointsEnabled -# } -# } -# } -# It 'throws when AutomaticCheckpointsEnabled is configured but not supported' { -# { Test-TargetResource -Name 'VMAutomaticCheckpoinstUnsupported' -AutomaticCheckpointsEnabled $true @testParams } | Should -Throw -# } - -# Mock -CommandName Get-Command -ParameterFilter { $Name -eq 'Set-VM' -and $Module -eq 'Hyper-V' } -MockWith { -# [pscustomobject]@{ -# parameters = @{ -# 'AutomaticCheckpointsEnabled' = '' -# } -# } -# } -# It 'Returns $true when AutomaticCheckpointsEnabled is on and requested "AutomaticCheckpointsEnabled" is not requested' { -# Test-TargetResource -Name 'VMWithAutomaticCheckpoints' @testParams | Should -Be $true -# } -# It 'Returns $true when AutomaticCheckpointsEnabled is on and requested "AutomaticCheckpointsEnabled" = "$true"' { -# Test-TargetResource -Name 'VMWithAutomaticCheckpoints' -AutomaticCheckpointsEnabled $true @testParams | Should -Be $true -# } -# It 'Returns $true when AutomaticCheckpointsEnabled is off and requested "AutomaticCheckpointsEnabled" = "$false"' { -# Test-TargetResource -Name 'VMWithoutAutomaticCheckpoints' -AutomaticCheckpointsEnabled $false @testParams | Should -Be $true -# } -# It 'Returns $false when AutomaticCheckpointsEnabled is off and requested "AutomaticCheckpointsEnabled" = "$true"' { -# Test-TargetResource -Name 'VMWithoutAutomaticCheckpoints' -AutomaticCheckpointsEnabled $true @testParams | Should -Be $false -# } -# It 'Returns $false when AutomaticCheckpointsEnabled is on and requested "AutomaticCheckpointsEnabled" = "$false"' { -# Test-TargetResource -Name 'VMWithAutomaticCheckpoints' -AutomaticCheckpointsEnabled $false @testParams | Should -Be $false -# } - -# It 'Returns $true when EnableGuestService is on and requested "EnableGuestService" = "$true"' { -# Mock -CommandName Get-VMIntegrationService -MockWith { -# $guestServiceInterface = [Microsoft.HyperV.PowerShell.VMIntegrationComponent]::CreateTypeInstance() -# $guestServiceInterface.Enabled = $true -# $guestServiceInterface.Id = $stubGuestServiceInterfaceId - -# return $guestServiceInterface -# } - -# Test-TargetResource -Name 'RunningVM' -EnableGuestService $true @testParams | Should -Be $true -# } - -# It 'throws when Hyper-V Tools are not installed' { -# # This test needs to be the last in the Context otherwise all subsequent Get-Module checks will fail -# Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } -# { Test-TargetResource -Name 'RunningVM' @testParams } | Should -Throw -# } - -# } #end context Validates Test-TargetResource Method - -# Context 'Validates Set-TargetResource Method' { -# $testParams = @{ -# VhdPath = $stubVhdxDisk.Path -# } - -# Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'NewVM' } -# Mock -CommandName New-VM -MockWith { -# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() -# $stubVM.Name = 'NewVM' -# $stubVM.Path = $StubVMConfig.FullPath -# $stubVM.Generation = $Generation -# $stubVM.ID = $mockVmGuid -# $stubVM.State = 'Off' - -# return $stubVM -# } - -# Mock -CommandName Set-VM -MockWith { return $true } -# Mock -CommandName Stop-VM -MockWith { return $true } # requires output to be able to pipe something into Remove-VM -# Mock -CommandName Remove-VM -MockWith { return $true } -# Mock -CommandName Set-VMNetworkAdapter -MockWith { return $true } -# Mock -CommandName Get-VMNetworkAdapter -MockWith { return $stubVM.NetworkAdapters.IpAddresses } -# Mock -CommandName Set-VMState -MockWith { return $true } -# Mock -CommandName Set-VMMemory - -# It 'Removes an existing VM when "Ensure" = "Absent"' { -# Set-TargetResource -Name 'RunningVM' -Ensure Absent @testParams -# Assert-MockCalled -CommandName Remove-VM -Scope It -# } - -# It 'Creates and starts a VM VM with disabled dynamic memory that does not exist when "Ensure" = "Present" and "State" = "Running"' { -# Set-TargetResource -Name 'NewVM' -State Running @testParams -# Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It -# Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It -# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 1 -Scope It -# } - -# It 'Creates but does not start a VM with disabled dynamic memory that does not exist when "Ensure" = "Present"' { -# Set-TargetResource -Name 'NewVM' @testParams -# Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It -# Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It -# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It -# } - -# It 'Creates but does not start a VM with disabled dynamic memory when only StartupMemory is specified' { -# Set-TargetResource -Name 'NewVM' @testParams -StartupMemory 4GB -# Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It -# Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It -# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It -# } - -# It 'Creates but does not start a VM with disabled dynamic memory when identical values for startup, minimum and maximum memory are specified' { -# Set-TargetResource -Name 'NewVM' @testParams -StartupMemory 4GB -MinimumMemory 4GB -MaximumMemory 4GB -# Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It -# Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It -# Assert-MockCalled -CommandName Set-VMMemory -Exactly -Times 1 -Scope It -# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It -# } - -# It 'Creates but does not start a VM with enabled dynamic memory because a MinimumMemory value is specified' { -# Set-TargetResource -Name 'NewVM' @testParams -MinimumMemory 512MB -# Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It -# Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It -# Assert-MockCalled -CommandName Set-VMMemory -Exactly -Times 0 -Scope It -# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It -# } - -# It 'Creates but does not start a VM with enabled dynamic memory because a MaximumMemory value is specified' { -# Set-TargetResource -Name 'NewVM' @testParams -MaximumMemory 16GB -# Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It -# Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It -# Assert-MockCalled -CommandName Set-VMMemory -Exactly -Times 0 -Scope It -# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It -# } - -# It 'Does not change VM state when VM "State" = "Running" and requested "State" = "Running"' { -# Set-TargetResource -Name 'RunningVM' -State Running @testParams -# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It -# } - -# It 'Does not change VM state when VM "State" = "Off" and requested "State" = "Off"' { -# Set-TargetResource -Name 'StoppedVM' -State Off @testParams -# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It -# } - -# It 'Changes VM state when existing VM "State" = "Off" and requested "State" = "Running"' { -# Set-TargetResource -Name 'StoppedVM' -State Running @testParams -# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 1 -Scope It -# } - -# It 'Changes VM state when existing VM "State" = "Running" and requested "State" = "Off"' { -# Set-TargetResource -Name 'RunningVM' -State Off @testParams -# Assert-MockCalled -CommandName Set-VMState -Exactly -Times 1 -Scope It -# } - -# It 'Creates a generation 1 VM by default/when not explicitly specified' { -# Set-TargetResource -Name 'NewVM' @testParams -# Assert-MockCalled -CommandName New-VM -ParameterFilter { $Generation -eq 1 } -Scope It -# } - -# It 'Creates a generation 1 VM when explicitly specified' { -# Set-TargetResource -Name 'NewVM' -Generation 1 @testParams -# Assert-MockCalled -CommandName New-VM -ParameterFilter { $Generation -eq 1 } -Scope It -# } - -# It 'Creates a generation 2 VM when explicitly specified' { -# Set-TargetResource -Name 'NewVM' -Generation 2 @testParams -# Assert-MockCalled -CommandName New-VM -ParameterFilter { $Generation -eq 2 } -Scope It -# } - -# It 'Calls "Add-VMNetworkAdapter" for each NIC when creating a new VM' { -# Mock -CommandName Add-VMNetworkAdapter -# Set-TargetResource -Name 'NewVM' @testParams -SwitchName 'Switch1', 'Switch2' -# # The first NIC is assigned during the VM creation -# Assert-MockCalled -CommandName Add-VMNetworkAdapter -Exactly 1 -Scope It -# } - -# It 'Calls "Connect-VMNetworkAdapter" for each existing NIC when updating an existing VM' { -# Mock -CommandName Connect-VMNetworkAdapter -# Set-TargetResource -Name 'StoppedVM' @testParams -SwitchName 'Switch1', 'Switch2' -# # The first NIC is assigned during the VM creation -# Assert-MockCalled -CommandName Connect-VMNetworkAdapter -Exactly 2 -Scope It -# } - -# It 'Calls "Add-VMNetworkAdapter" for each missing NIC when updating an existing VM' { -# Mock -CommandName Connect-VMNetworkAdapter -# Mock -CommandName Add-VMNetworkAdapter -# Set-TargetResource -Name 'StoppedVM' @testParams -SwitchName 'Switch1', 'Switch2', 'Switch3' -# # The first NIC is assigned during the VM creation -# Assert-MockCalled -CommandName Connect-VMNetworkAdapter -Exactly 2 -Scope It -# Assert-MockCalled -CommandName Add-VMNetworkAdapter -Exactly 1 -Scope It -# } - -# It 'Does not change switch assignments if no switch assignments are specified' { -# Mock -CommandName Connect-VMNetworkAdapter -# Set-TargetResource -Name 'StoppedVM' @testParams -# Assert-MockCalled -CommandName Connect-VMNetworkAdapter -Exactly 0 -Scope It -# } - -# It 'Does not change NIC assignments if the switch assisgnments are correct' { -# Mock -CommandName Set-VMNetworkAdapter -# Set-TargetResource -Name 'StoppedVM' @testParams -SwitchName $stubNIC1.SwitchName, $stubNIC2.SwitchName -# Assert-MockCalled -CommandName Set-VMNetworkAdapter -Exactly 0 -Scope It -# } - -# It 'Errors when updating MAC addresses on a running VM and "RestartIfNeeded" = "$false"' { -# { Set-TargetResource -Name 'RunningVM' @testParams -MACAddress 'AABBCCDDEEFE', 'AABBCCDDEEFF' -ErrorAction Stop } | Should -Throw -# } - -# It 'Does not change MAC addresses if no MAC addresses assignments are specified' { -# Mock -CommandName Set-VMNetworkAdapter -ParameterFilter { $StaticMacAddress -ne $null } -# Set-TargetResource -Name 'StoppedVM' @testParams -# Assert-MockCalled -CommandName Set-VMNetworkAdapter -ParameterFilter { $StaticMacAddress -ne $null } -Exactly 0 -Scope It -# } - -# It 'Calls "Set-VMNetworkAdapter" for each MAC address on a stopped VM' { -# Mock -CommandName Set-VMNetworkAdapter -# Set-TargetResource -Name 'StoppedVM' @testParams -MACAddress 'AABBCCDDEEFE', 'AABBCCDDEEFF' -# # The first NIC is assigned during the VM creation -# Assert-MockCalled -CommandName Set-VMNetworkAdapter -Exactly 2 -Scope It -# } - -# It 'Does not change Secure Boot call "Set-VMProperty" when creating a generation 1 VM' { -# Mock -CommandName Set-VMProperty -# Set-TargetResource -Name 'RunningVM' @testParams -# Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 0 -Scope It -# } - -# It 'Does call "Set-VMProperty" when creating a generation 2 VM' { -# Mock -CommandName Test-VMSecureBoot -MockWith { return $true } -# Mock -CommandName Set-VMProperty -# Set-TargetResource -Name 'RunningVM' -Generation 2 -SecureBoot $false @testParams -# Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 1 -Scope It -# } - -# It 'Does not change Secure Boot for generation 1 VM' { -# Mock -CommandName Test-VMSecureBoot -MockWith { return $true } -# Mock -CommandName Set-VMProperty -# Set-TargetResource -Name 'StoppedVM' -SecureBoot $true @testParams -# Set-TargetResource -Name 'StoppedVM' -SecureBoot $false @testParams -# Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 0 -Scope It -# } - -# It 'Does not change Secure Boot for generation 2 VM with VM "SecureBoot" match' { -# Mock -CommandName Test-VMSecureBoot -MockWith { return $true } -# Mock -CommandName Set-VMProperty -# Set-TargetResource -Name 'StoppedVM' -SecureBoot $true -Generation 2 @testParams -# Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 0 -Scope It -# } - -# It 'Does change Secure Boot for generation 2 VM with VM "SecureBoot" mismatch' { -# Mock -CommandName Test-VMSecureBoot -MockWith { return $false } -# Mock -CommandName Set-VMProperty -# Set-TargetResource -Name 'StoppedVM' -SecureBoot $true -Generation 2 @testParams -# Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 1 -Scope It -# } - -# It 'Does call "Enable-VMIntegrationService" when "EnableGuestService" = "$true"' { -# Mock -CommandName Enable-VMIntegrationService -# Set-TargetResource -Name 'RunningVM' -EnableGuestService $true @testParams -# Assert-MockCalled -CommandName Enable-VMIntegrationService -Exactly -Times 1 -Scope It -# } - -# It 'Does call "Disable-VMIntegrationService" when "Guest Service Interface" = "Enabled" and "EnableGuestService" = "$false" specified' { -# Mock -CommandName Disable-VMIntegrationService -# Mock -CommandName Get-VMIntegrationService -MockWith { -# $guestServiceInterface = [Microsoft.HyperV.PowerShell.VMIntegrationComponent]::CreateTypeInstance() -# $guestServiceInterface.Enabled = $true -# $guestServiceInterface.Id = $stubGuestServiceInterfaceId - -# return $guestServiceInterface -# } - -# Set-TargetResource -Name 'RunningVM' -EnableGuestService $false @testParams -# Assert-MockCalled -CommandName Disable-VMIntegrationService -Exactly -Times 1 -Scope It -# } - -# Mock -CommandName Get-Command -ParameterFilter { $Name -eq 'Set-VM' -and $Module -eq 'Hyper-V' } -MockWith { -# [pscustomobject]@{ -# parameters = @{ -# # Does not contain parameter AutomaticCheckpointsEnabled -# } -# } -# } -# It 'throws when AutomaticCheckpointsEnabled is configured but not supported' { -# { Set-TargetResource -Name 'VMAutomaticCheckpointsUnsupported' -AutomaticCheckpointsEnabled $true @testParams } | Should -Throw -# } -# It 'Does not call "Set-VM" when "AutomaticCheckpointsEnabled" is unsupported and unspecified' { -# Set-TargetResource -Name 'VMAutomaticCheckpointsUnsupported' @testParams -# Assert-MockCalled -CommandName Set-VM -Exactly -Times 0 -Scope It -# } - -# Mock -CommandName Get-Command -ParameterFilter { $Name -eq 'Set-VM' -and $Module -eq 'Hyper-V' } -MockWith { -# [pscustomobject]@{ -# parameters = @{ -# 'AutomaticCheckpointsEnabled' = '' -# } -# } -# } -# $AutomaticCheckpointsEnabledTestCases = @( -# @{ -# VMName = 'VMWithAutomaticCheckpoints' -# SetAutomaticCheckpointsEnabled = $true -# Assert = 'Does not call "Set-VM"' -# Times = 0 -# }, -# @{ -# VMName = 'VMWithoutAutomaticCheckpoints' -# SetAutomaticCheckpointsEnabled = $false -# Assert = 'Does not call "Set-VM"' -# Times = 0 -# }, -# @{ -# VMName = 'VMWithAutomaticCheckpoints' -# SetAutomaticCheckpointsEnabled = $false -# Assert = 'Does call "Set-VM"' -# Times = 1 -# }, -# @{ -# VMName = 'VMWithoutAutomaticCheckpoints' -# SetAutomaticCheckpointsEnabled = $true -# Assert = 'Does call "Set-VM"' -# Times = 1 -# } -# ) -# It ' on VM when "AutomaticCheckpointsEnabled" is set to ""' -TestCases $AutomaticCheckpointsEnabledTestCases { -# param -# ( -# $VMName, -# $SetAutomaticCheckpointsEnabled, -# $Times -# ) - -# Set-TargetResource -Name $VMName -AutomaticCheckpointsEnabled $SetAutomaticCheckpointsEnabled @testParams -# Assert-MockCalled -CommandName Set-VM -ParameterFilter { $Name -eq $VMName -and $AutomaticCheckpointsEnabled -eq $SetAutomaticCheckpointsEnabled } -Exactly -Times $Times -Scope It -# } -# It 'Disables dynamic memory of RuningVM if only StartupMemory specified' { -# Mock -CommandName Set-VMProperty -# Set-TargetResource -Name 'RunningVM' -StartupMemory 4GB @testParams -# Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { -# $VMCommand -eq 'Set-VM' -and -# ($ChangeProperty.StaticMemory -eq $true) -and -# ($ChangeProperty.DynamicMemory -eq $false) -# } -Exactly -Times 1 -Scope It -# } - -# It 'Disables dynamic memory of RunningVM if StartupMemory, MinimumMemory and MaximumMemory are specified with the same values' { -# Mock -CommandName Set-VMProperty -# Set-TargetResource -Name 'RunningVM' -StartupMemory 4GB -MinimumMemory 4GB -MaximumMemory 4GB @testParams -# Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { -# $VMCommand -eq 'Set-VM' -and -# ($ChangeProperty.StaticMemory -eq $true) -and -# ($ChangeProperty.DynamicMemory -eq $false) -# } -Exactly -Times 1 -Scope It -# } - -# It 'Enables dynamic memory of RuningVM if MinimumMemory is specified ' { -# Mock -CommandName Set-VMProperty -# Set-TargetResource -Name 'RunningVM' -MinimumMemory 4GB @testParams -# Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { -# $VMCommand -eq 'Set-VM' -and -# ($ChangeProperty.StaticMemory -eq $false) -and -# ($ChangeProperty.DynamicMemory -eq $true) -# } -Exactly -Times 1 -Scope It -# } - -# It 'Enables dynamic memory of RuningVM if MaximumMemory is specified ' { -# Mock -CommandName Set-VMProperty -# Set-TargetResource -Name 'RunningVM' -MaximumMemory 4GB @testParams -# Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { -# $VMCommand -eq 'Set-VM' -and -# ($ChangeProperty.StaticMemory -eq $false) -and -# ($ChangeProperty.DynamicMemory -eq $true) -# } -Exactly -Times 1 -Scope It -# } - -# It 'throws when Hyper-V Tools are not installed' { -# Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } -# { Set-TargetResource -Name 'RunningVM' @testParams } | Should -Throw -# } -# } #end context Validates Set-TargetResource Method - -# Context 'Validates Test-VMSecureBoot Method' { -# BeforeAll { -# Mock -CommandName Get-VM -MockWith { -# $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() -# $stubVM.Name = 'NewVM' -# $stubVM.Path = $StubVMConfig.FullPath -# $stubVM.Generation = $Generation -# $stubVM.ID = $mockVmGuid -# $stubVM.State = 'Off' - -# return $stubVM -# } -# } - -# It 'Returns $true when "SecureBoot" = "On"' { -# Mock -CommandName Get-VMFirmware -MockWith { -# return [PSCustomObject] @{ -# SecureBoot = 'On' -# } -# } - -# Test-VMSecureBoot -Name 'TestVM' | Should -Be $true -# } - -# It 'Returns $false when "SecureBoot" = "Off"' { -# Mock -CommandName Get-VMFirmware -MockWith { -# return [PSCustomObject] @{ -# SecureBoot = 'Off' -# } -# } - -# Test-VMSecureBoot -Name 'TestVM' | Should -Be $false -# } - -# } #end context Validates Test-VMSecureBoot Method - -# Context 'Validates Get-VhdHierarchy Method' { -# It 'Does not throw with null parent path (#52)' { -# # Must use a different file extension to ensure existing mocks Get-VhdHierarchy or not called -# $fakeVhdPath = 'BaseVhd.avhdx' - -# Mock -CommandName Get-VHD -ParameterFilter { $Path -eq $fakeVhdPath } -MockWith { -# return [PSCustomObject] @{ -# Path = $fakeVhdPath -# ParentPath = $null -# } -# } - -# { Get-VhdHierarchy -VhdPath $fakeVhdPath } | Should -Not -throw -# } - -# } #end context validates Get-VhdHierarchy -# } #end describe xVMHyper-V -# } #end inmodulescope -# } -# finally -# { -# Invoke-TestCleanup -# } +$script:dscModuleName = 'HyperVDsc' +$script:dscResourceName = 'DSC_VMHyperV' + +function Invoke-TestSetup +{ + try + { + Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + } + + $script:testEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:dscModuleName ` + -DSCResourceName $script:dscResourceName ` + -ResourceType 'Mof' ` + -TestType 'Unit' + + # Import the stub functions. + Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +} + +function Invoke-TestCleanup +{ + Restore-TestEnvironment -TestEnvironment $script:testEnvironment +} + +Invoke-TestSetup + +try +{ + InModuleScope $script:dscResourceName { + Describe 'xVMHyper-V' { + $null = New-Item -Path 'TestDrive:\TestVM.vhdx' -ItemType File + $null = New-Item -Path 'TestDrive:\TestVM.vhd' -ItemType File + + $stubVhdxDisk = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() + $stubVhdxDisk.Path = 'TestDrive:\TestVM.vhdx' + + $stubVhdDisk = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() + $stubVhdDisk.Path = 'TestDrive:\TestVM.vhd' + + $studVhdxDiskSnapshot = New-Item -Path "TestDrive:\TestVM_D0145678-1576-4435-AB18-9F000C1C17D0.avhdx" -ItemType File + $StubVMConfig = New-Item -Path 'TestDrive:\TestVM.xml' -ItemType File + + # Mock the class VMNetworkAdapter to support piping to cmdlet Connect-VMNetworkAdapter + $stubNIC1 = [Microsoft.HyperV.PowerShell.VMNetworkAdapter]::CreateTypeInstance() + $stubNIC1.SwitchName = 'Test Switch 1' + $stubNIC1.MacAddress = 'AA-BB-CC-DD-EE-FF' + $stubNIC1.IpAddresses = @('192.168.0.1', '10.0.0.1') + + # Mock the class VMNetworkAdapter to support piping to cmdlet Connect-VMNetworkAdapter + $stubNIC2 = [Microsoft.HyperV.PowerShell.VMNetworkAdapter]::CreateTypeInstance() + $stubNIC2.SwitchName = 'Test Switch 2' + $stubNIC2.MacAddress = 'AA-BB-CC-DD-EE-FE' + $stubNIC2.IpAddresses = @('192.168.1.1') + + $mockVmGuid = [System.Guid]::NewGuid().ToString() + + Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'RunningVM' } -MockWith { + $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() + $stubVM.Name = 'RunningVM' + $stubVM.HardDrives = @( + $stubVhdxDisk, + $stubVhdDisk + ) + $stubVM.Path = $StubVMConfig.FullPath + $stubVM.Generation = 1 + $stubVM.MemoryStartup = 512MB + $stubVM.MemoryMinimum = 128MB + $stubVM.MemoryMaximum = 4096MB + $stubVM.ProcessorCount = 1 + $stubVM.ID = $mockVmGuid + $stubVM.CPUUsage = 10 + $stubVM.MemoryAssigned = 512MB + $stubVM.Uptime = New-TimeSpan -Hours 12 + $stubVM.CreationTime = (Get-Date).AddHours(-12) + $stubVM.DynamicMemoryEnabled = $true + $stubVM.Notes = '' + $stubVM.State = 'Running' + $stubVM.NetworkAdapters = @( + $stubNIC1, + $stubNIC2 + ) + + return $stubVM + } + + Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'StoppedVM' } -MockWith { + $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() + $stubVM.Name = 'StoppedVM' + $stubVM.HardDrives = @( + $stubVhdxDisk, + $stubVhdDisk + ) + $stubVM.Path = $StubVMConfig.FullPath + $stubVM.Generation = 1 + $stubVM.MemoryStartup = 512MB + $stubVM.MemoryMinimum = 128MB + $stubVM.MemoryMaximum = 4096MB + $stubVM.ProcessorCount = 1 + $stubVM.ID = $mockVmGuid + $stubVM.CPUUsage = 10 + $stubVM.MemoryAssigned = 512MB + $stubVM.Uptime = New-TimeSpan -Hours 12 + $stubVM.CreationTime = (Get-Date).AddHours(-12) + $stubVM.DynamicMemoryEnabled = $true + $stubVM.Notes = '' + $stubVM.State = 'Off' + $stubVM.NetworkAdapters = @( + $stubNIC1, + $stubNIC2 + ) + + return $stubVM + } + + Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'PausedVM' } -MockWith { + $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() + $stubVM.Name = 'PausedVM' + $stubVM.HardDrives = @( + $stubVhdxDisk, + $stubVhdDisk + ) + $stubVM.Path = $StubVMConfig.FullPath + $stubVM.Generation = 1 + $stubVM.MemoryStartup = 512MB + $stubVM.MemoryMinimum = 128MB + $stubVM.MemoryMaximum = 4096MB + $stubVM.ProcessorCount = 1 + $stubVM.ID = $mockVmGuid + $stubVM.CPUUsage = 10 + $stubVM.MemoryAssigned = 512MB + $stubVM.Uptime = New-TimeSpan -Hours 12 + $stubVM.CreationTime = (Get-Date).AddHours(-12) + $stubVM.DynamicMemoryEnabled = $true + $stubVM.Notes = '' + $stubVM.State = 'Paused' + $stubVM.NetworkAdapters = @( + $stubNIC1, + $stubNIC2 + ) + + return $stubVM + } + + Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'NonexistentVM' } -MockWith { + Write-Error 'VM not found.' + } + + Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'DuplicateVM' } -MockWith { + $stubVM1 = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() + $stubVM1.Name = 'DuplicateVM' + $stubVM1.HardDrives = @( + $stubVhdxDisk, + $stubVhdDisk + ) + $stubVM1.Path = $StubVMConfig.FullPath + $stubVM1.Generation = 1 + $stubVM1.MemoryStartup = 512MB + $stubVM1.MemoryMinimum = 128MB + $stubVM1.MemoryMaximum = 4096MB + $stubVM1.ProcessorCount = 1 + $stubVM1.ID = $mockVmGuid + $stubVM1.CPUUsage = 10 + $stubVM1.MemoryAssigned = 512MB + $stubVM1.Uptime = New-TimeSpan -Hours 12 + $stubVM1.CreationTime = (Get-Date).AddHours(-12) + $stubVM1.DynamicMemoryEnabled = $true + $stubVM1.Notes = '' + $stubVM1.State = 'Off' + $stubVM1.NetworkAdapters = @( + $stubNIC1, + $stubNIC2 + ) + + $stubVM2 = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() + $stubVM2.Name = 'DuplicateVM' + $stubVM2.HardDrives = @( + $stubVhdxDisk, + $stubVhdDisk + ) + $stubVM2.Path = $StubVMConfig.FullPath + $stubVM2.Generation = 1 + $stubVM2.MemoryStartup = 512MB + $stubVM2.MemoryMinimum = 128MB + $stubVM2.MemoryMaximum = 4096MB + $stubVM2.ProcessorCount = 1 + $stubVM2.ID = $mockVmGuid + $stubVM2.CPUUsage = 10 + $stubVM2.MemoryAssigned = 512MB + $stubVM2.Uptime = New-TimeSpan -Hours 12 + $stubVM2.CreationTime = (Get-Date).AddHours(-12) + $stubVM2.DynamicMemoryEnabled = $true + $stubVM2.Notes = '' + $stubVM2.State = 'Off' + $stubVM2.NetworkAdapters = @( + $stubNIC1, + $stubNIC2 + ) + + return @( + $stubVM1, + $stubVM2 + ) + } + + Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'Generation1Vhd' } -MockWith { + $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() + $stubVM.Name = 'Generation1Vhd' + $stubVM.HardDrives = @( + $stubVhdDisk + ) + $stubVM.Path = $StubVMConfig.FullPath + $stubVM.Generation = 1 + $stubVM.MemoryStartup = 512MB + $stubVM.MemoryMinimum = 128MB + $stubVM.MemoryMaximum = 4096MB + $stubVM.ProcessorCount = 1 + $stubVM.ID = $mockVmGuid + $stubVM.CPUUsage = 10 + $stubVM.MemoryAssigned = 512MB + $stubVM.Uptime = New-TimeSpan -Hours 12 + $stubVM.CreationTime = (Get-Date).AddHours(-12) + $stubVM.DynamicMemoryEnabled = $true + $stubVM.Notes = '' + $stubVM.State = 'Running' + $stubVM.NetworkAdapters = @( + $stubNIC1, + $stubNIC2 + ) + + return $stubVM + } + + Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'Generation2VM' } -MockWith { + $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() + $stubVM.Name = 'Generation2VM' + $stubVM.HardDrives = @( + $stubVhdxDisk + ) + $stubVM.Path = $StubVMConfig.FullPath + $stubVM.Generation = 2 + $stubVM.MemoryStartup = 512MB + $stubVM.MemoryMinimum = 128MB + $stubVM.MemoryMaximum = 4096MB + $stubVM.ProcessorCount = 1 + $stubVM.ID = $mockVmGuid + $stubVM.CPUUsage = 10 + $stubVM.MemoryAssigned = 512MB + $stubVM.Uptime = New-TimeSpan -Hours 12 + $stubVM.CreationTime = (Get-Date).AddHours(-12) + $stubVM.DynamicMemoryEnabled = $true + $stubVM.Notes = '' + $stubVM.State = 'Running' + $stubVM.NetworkAdapters = @( + $stubNIC1, + $stubNIC2 + ) + + return $stubVM + } + + Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'VMWithAutomaticCheckpoints' } -MockWith { + $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() + $stubVM.Name = 'VMWithAutomaticCheckpoints' + $stubVM.HardDrives = @( + $stubVhdxDisk + ) + $stubVM.Path = $StubVMConfig.FullPath + $stubVM.Generation = 2 + $stubVM.MemoryStartup = 512MB + $stubVM.MemoryMinimum = 128MB + $stubVM.MemoryMaximum = 4096MB + $stubVM.ProcessorCount = 1 + $stubVM.ID = $mockVmGuid + $stubVM.CPUUsage = 10 + $stubVM.MemoryAssigned = 512MB + $stubVM.Uptime = New-TimeSpan -Hours 12 + $stubVM.CreationTime = (Get-Date).AddHours(-12) + $stubVM.DynamicMemoryEnabled = $true + $stubVM.Notes = '' + $stubVM.State = 'Running' + $stubVM.AutomaticCheckpointsEnabled = $true + $stubVM.NetworkAdapters = @( + $stubNIC1, + $stubNIC2 + ) + + return $stubVM + } + + Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'VMWithoutAutomaticCheckpoints' } -MockWith { + $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() + $stubVM.Name = 'VMWithoutAutomaticCheckpoints' + $stubVM.HardDrives = @( + $stubVhdxDisk + ) + $stubVM.Path = $StubVMConfig.FullPath + $stubVM.Generation = 2 + $stubVM.MemoryStartup = 512MB + $stubVM.MemoryMinimum = 128MB + $stubVM.MemoryMaximum = 4096MB + $stubVM.ProcessorCount = 1 + $stubVM.ID = $mockVmGuid + $stubVM.CPUUsage = 10 + $stubVM.MemoryAssigned = 512MB + $stubVM.Uptime = New-TimeSpan -Hours 12 + $stubVM.CreationTime = (Get-Date).AddHours(-12) + $stubVM.DynamicMemoryEnabled = $true + $stubVM.Notes = '' + $stubVM.State = 'Running' + $stubVM.AutomaticCheckpointsEnabled = $false + $stubVM.NetworkAdapters = @( + $stubNIC1, + $stubNIC2 + ) + + return $stubVM + } + + Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'VMAutomaticCheckpointsUnsupported' } -MockWith { + $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() + $stubVM.Name = 'VMAutomaticCheckpointsUnsupported' + $stubVM.HardDrives = @( + $stubVhdxDisk + ) + $stubVM.Path = $StubVMConfig.FullPath + $stubVM.Generation = 2 + $stubVM.MemoryStartup = 512MB + $stubVM.MemoryMinimum = 128MB + $stubVM.MemoryMaximum = 4096MB + $stubVM.ProcessorCount = 1 + $stubVM.ID = $mockVmGuid + $stubVM.CPUUsage = 10 + $stubVM.MemoryAssigned = 512MB + $stubVM.Uptime = New-TimeSpan -Hours 12 + $stubVM.CreationTime = (Get-Date).AddHours(-12) + $stubVM.DynamicMemoryEnabled = $true + $stubVM.Notes = '' + $stubVM.State = 'Running' + $stubVM.NetworkAdapters = @( + $stubNIC1, + $stubNIC2 + ) + + return $stubVM + } + + $stubGuestServiceInterfaceId = 'Microsoft:{0}\6C09BB55-D683-4DA0-8931-C9BF705F6480' -f $mockVmGuid + + Mock -CommandName Get-VMIntegrationService -MockWith { + $guestServiceInterface = [Microsoft.HyperV.PowerShell.VMIntegrationComponent]::CreateTypeInstance() + $guestServiceInterface.Enabled = $false + $guestServiceInterface.Id = $stubGuestServiceInterfaceId + + return $guestServiceInterface + } + + Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } -MockWith { return $true } + Mock -CommandName Get-VhdHierarchy -ParameterFilter { $VhdPath.EndsWith('.vhd') } -MockWith { + # Return single Vhd chain for .vhds + return @($stubVhdDisk.Path) + } + Mock -CommandName Get-VhdHierarchy -ParameterFilter { $VhdPath.EndsWith('.vhdx') } -MockWith { + # Return snapshot hierarchy for .vhdxs + return @($stubVhdxDiskSnapshot.FullName, $stubVhdxDisk.Path) + } + Context 'Validates Get-TargetResource Method' { + + It 'Returns a hashtable' { + $targetResource = Get-TargetResource -Name 'RunningVM' -VhdPath $stubVhdxDisk.Path + $targetResource -is [System.Collections.Hashtable] | Should -Be $true + } + + It 'throws when multiple VMs are present' { + { Get-TargetResource -Name 'DuplicateVM' -VhdPath $stubVhdxDisk.Path } | Should -Throw + } + + It 'Does not call Get-VMFirmware if a generation 1 VM' { + Mock -CommandName Get-VMFirmware -MockWith { throw } + $null = Get-TargetResource -Name 'RunningVM' -VhdPath $stubVhdxDisk.Path + Assert-MockCalled -CommandName Get-VMFirmware -Scope It -Exactly 0 + } + + It 'Calls Get-VMFirmware if a generation 2 VM' { + Mock -CommandName Get-VMFirmware -MockWith { return $true } + $null = Get-TargetResource -Name 'Generation2VM' -VhdPath $stubVhdxDisk.Path + Assert-MockCalled -CommandName Get-VMFirmware -Scope It -Exactly 1 + } + + It 'Hash table contains key EnableGuestService' { + $targetResource = Get-TargetResource -Name 'RunningVM' -VhdPath $stubVhdxDisk.Path + $targetResource.ContainsKey('EnableGuestService') | Should -Be $true + } + It 'Hash table contains key AutomaticCheckpointEnabled' { + $targetResource = Get-TargetResource -Name 'VMWithAutomaticCheckpoints' -VhdPath $stubVhdxDisk.Path + $targetResource.ContainsKey('AutomaticCheckpointsEnabled') | Should -Be $true + } + It 'throws when Hyper-V Tools are not installed' { + # This test needs to be the last in the Context otherwise all subsequent Get-Module checks will fail + Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } + { Get-TargetResource -Name 'RunningVM' @testParams } | Should -Throw + } + } #end context Validates Get-TargetResource Method + + Context 'Validates Test-TargetResource Method' { + $testParams = @{ + VhdPath = $stubVhdxDisk.Path + } + + It 'Returns a boolean' { + $targetResource = Test-TargetResource -Name 'RunningVM' @testParams + $targetResource -is [System.Boolean] | Should -Be $true + } + + It 'Returns $true when VM is present and "Ensure" = "Present"' { + Test-TargetResource -Name 'RunningVM' @testParams | Should -Be $true + } + + It 'Returns $false when VM is not present and "Ensure" = "Present"' { + Test-TargetResource -Name 'NonexistentVM' @testParams | Should -Be $false + } + + It 'Returns $true when VM is not present and "Ensure" = "Absent"' { + Test-TargetResource -Name 'NonexistentVM' -Ensure Absent @testParams | Should -Be $true + } + + It 'Returns $false when VM is present and "Ensure" = "Absent"' { + Test-TargetResource -Name 'RunningVM' -Ensure Absent @testParams | Should -Be $false + } + + It 'Returns $true when VM is in the "Running" state and no state is explicitly specified' { + Test-TargetResource -Name 'RunningVM' @testParams | Should -Be $true + } + + It 'Returns $true when VM is in the "Stopped" state and no state is explicitly specified' { + Test-TargetResource -Name 'StoppedVM' @testParams | Should -Be $true + } + + It 'Returns $true when VM is in the "Paused" state and no state is explicitly specified' { + Test-TargetResource -Name 'PausedVM' @testParams | Should -Be $true + } + + It 'Returns $true when VM is in the "Running" state and requested "State" = "Running"' { + Test-TargetResource -Name 'RunningVM' @testParams | Should -Be $true + } + + It 'Returns $true when VM is in the "Off" state and requested "State" = "Off"' { + Test-TargetResource -Name 'StoppedVM' -State Off @testParams | Should -Be $true + } + + It 'Returns $true when VM is in the "Paused" state and requested "State" = Paused"' { + Test-TargetResource -Name 'PausedVM' -State Paused @testParams | Should -Be $true + } + + It 'Returns $false when VM is in the "Running" state and requested "State" = "Off"' { + Test-TargetResource -Name 'RunningVM' -State Off @testParams | Should -Be $false + } + + It 'Returns $false when VM is in the "Off" state and requested "State" = "Runnning"' { + Test-TargetResource -Name 'StoppedVM' -State Running @testParams | Should -Be $false + } + + It 'Returns $true when VM .vhd file is specified with a generation 1 VM' { + Test-TargetResource -Name 'Generation1Vhd' -VhdPath $stubVhdDisk.Path -Generation 1 -Verbose | Should -Be $true + } + + It 'Returns $true when VM .vhdx file is specified with a generation 1 VM' { + Test-TargetResource -Name 'StoppedVM' -VhdPath $stubVhdxDisk.Path -Generation 1 | Should -Be $true + } + + It 'Returns $true when VM .vhdx file is specified with a generation 2 VM' { + Mock -CommandName Test-VMSecureBoot -MockWith { return $true } + Test-TargetResource -Name 'Generation2VM' -Generation 2 @testParams | Should -Be $true + } + + It 'throws when a VM .vhd file is specified with a generation 2 VM' { + { Test-TargetResource -Name 'Gen2VM' -VhdPath $stubVhdDisk.Path -Generation 2 } | Should -Throw + } + + It 'Returns $true when multiple NICs are assigned in the correct order' { + Test-TargetResource -Name 'RunningVM' @testParams -SwitchName @($stubNIC1.SwitchName, $stubNIC2.SwitchName) | Should -Be $true + } + + It 'Returns $false when multiple NICs are not assigned/assigned in the wrong order' { + Test-TargetResource -Name 'RunningVM' @testParams -SwitchName @($stubNIC2.SwitchName, $stubNIC1.SwitchName) | Should -Be $false + } + + It 'Returns $true when multiple MAC addresses are assigned in the correct order' { + Test-TargetResource -Name 'RunningVM' @testParams -MACAddress @($stubNIC1.MACAddress, $stubNIC2.MACAddress) | Should -Be $true + } + + It 'Returns $false when multiple MAC addresses not assigned/assigned in the wrong order' { + Test-TargetResource -Name 'RunningVM' @testParams -MACAddress @($stubNIC1.MACAddress, $stubNIC2.MACAddress) | Should -Be $true + } + + It 'Returns $true regardless of "SecureBoot" setting on a generation 1 VM' { + Test-TargetResource -Name 'RunningVM' -SecureBoot $true @testParams | Should -Be $true + Test-TargetResource -Name 'RunningVM' -SecureBoot $false @testParams | Should -Be $true + } + + It 'Returns $true when SecureBoot is On and requested "SecureBoot" = "$true"' { + Mock -CommandName Test-VMSecureBoot -MockWith { return $true } + Test-TargetResource -Name 'Generation2VM' -Generation 2 @testParams | Should -Be $true + } + + It 'Returns $false when SecureBoot is On and requested "SecureBoot" = "$false"' { + Mock -CommandName Test-VMSecureBoot -MockWith { return $true } + Test-TargetResource -Name 'Generation2VM' -SecureBoot $false -Generation 2 @testParams | Should -Be $false + } + + It 'Returns $true when VM has snapshot chain' { + Mock -CommandName Get-VhdHierarchy -MockWith { + return @($studVhdxDiskSnapshot, $stubVhdxDisk) + } + Test-TargetResource -Name 'Generation2VM' -VhdPath $stubVhdxDisk.Path -Verbose | Should -Be $true + } + + It 'Returns $false when EnableGuestService is off and requested "EnableGuestService" = "$true"' { + Test-TargetResource -Name 'RunningVM' -EnableGuestService $true @testParams | Should -Be $false + } + + It 'Returns $true when EnableGuestService is off and "EnableGuestService" is not requested"' { + Test-TargetResource -Name 'RunningVM' @testParams | Should -Be $true + } + + Mock -CommandName Get-Command -ParameterFilter { $Name -eq 'Set-VM' -and $Module -eq 'Hyper-V' } -MockWith { + [pscustomobject]@{ + parameters = @{ + # Does not contains parameter AutomaticCheckpointsEnabled + } + } + } + It 'throws when AutomaticCheckpointsEnabled is configured but not supported' { + { Test-TargetResource -Name 'VMAutomaticCheckpoinstUnsupported' -AutomaticCheckpointsEnabled $true @testParams } | Should -Throw + } + + Mock -CommandName Get-Command -ParameterFilter { $Name -eq 'Set-VM' -and $Module -eq 'Hyper-V' } -MockWith { + [pscustomobject]@{ + parameters = @{ + 'AutomaticCheckpointsEnabled' = '' + } + } + } + It 'Returns $true when AutomaticCheckpointsEnabled is on and requested "AutomaticCheckpointsEnabled" is not requested' { + Test-TargetResource -Name 'VMWithAutomaticCheckpoints' @testParams | Should -Be $true + } + It 'Returns $true when AutomaticCheckpointsEnabled is on and requested "AutomaticCheckpointsEnabled" = "$true"' { + Test-TargetResource -Name 'VMWithAutomaticCheckpoints' -AutomaticCheckpointsEnabled $true @testParams | Should -Be $true + } + It 'Returns $true when AutomaticCheckpointsEnabled is off and requested "AutomaticCheckpointsEnabled" = "$false"' { + Test-TargetResource -Name 'VMWithoutAutomaticCheckpoints' -AutomaticCheckpointsEnabled $false @testParams | Should -Be $true + } + It 'Returns $false when AutomaticCheckpointsEnabled is off and requested "AutomaticCheckpointsEnabled" = "$true"' { + Test-TargetResource -Name 'VMWithoutAutomaticCheckpoints' -AutomaticCheckpointsEnabled $true @testParams | Should -Be $false + } + It 'Returns $false when AutomaticCheckpointsEnabled is on and requested "AutomaticCheckpointsEnabled" = "$false"' { + Test-TargetResource -Name 'VMWithAutomaticCheckpoints' -AutomaticCheckpointsEnabled $false @testParams | Should -Be $false + } + + It 'Returns $true when EnableGuestService is on and requested "EnableGuestService" = "$true"' { + Mock -CommandName Get-VMIntegrationService -MockWith { + $guestServiceInterface = [Microsoft.HyperV.PowerShell.VMIntegrationComponent]::CreateTypeInstance() + $guestServiceInterface.Enabled = $true + $guestServiceInterface.Id = $stubGuestServiceInterfaceId + + return $guestServiceInterface + } + + Test-TargetResource -Name 'RunningVM' -EnableGuestService $true @testParams | Should -Be $true + } + + It 'throws when Hyper-V Tools are not installed' { + # This test needs to be the last in the Context otherwise all subsequent Get-Module checks will fail + Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } + { Test-TargetResource -Name 'RunningVM' @testParams } | Should -Throw + } + + } #end context Validates Test-TargetResource Method + + Context 'Validates Set-TargetResource Method' { + $testParams = @{ + VhdPath = $stubVhdxDisk.Path + } + + Mock -CommandName Get-VM -ParameterFilter { $Name -eq 'NewVM' } + Mock -CommandName New-VM -MockWith { + $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() + $stubVM.Name = 'NewVM' + $stubVM.Path = $StubVMConfig.FullPath + $stubVM.Generation = $Generation + $stubVM.ID = $mockVmGuid + $stubVM.State = 'Off' + + return $stubVM + } + + Mock -CommandName Set-VM -MockWith { return $true } + Mock -CommandName Stop-VM -MockWith { return $true } # requires output to be able to pipe something into Remove-VM + Mock -CommandName Remove-VM -MockWith { return $true } + Mock -CommandName Set-VMNetworkAdapter -MockWith { return $true } + Mock -CommandName Get-VMNetworkAdapter -MockWith { return $stubVM.NetworkAdapters.IpAddresses } + Mock -CommandName Set-VMState -MockWith { return $true } + Mock -CommandName Set-VMMemory + + It 'Removes an existing VM when "Ensure" = "Absent"' { + Set-TargetResource -Name 'RunningVM' -Ensure Absent @testParams + Assert-MockCalled -CommandName Remove-VM -Scope It + } + + It 'Creates and starts a VM VM with disabled dynamic memory that does not exist when "Ensure" = "Present" and "State" = "Running"' { + Set-TargetResource -Name 'NewVM' -State Running @testParams + Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Set-VMState -Exactly -Times 1 -Scope It + } + + It 'Creates but does not start a VM with disabled dynamic memory that does not exist when "Ensure" = "Present"' { + Set-TargetResource -Name 'NewVM' @testParams + Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It + } + + It 'Creates but does not start a VM with disabled dynamic memory when only StartupMemory is specified' { + Set-TargetResource -Name 'NewVM' @testParams -StartupMemory 4GB + Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It + } + + It 'Creates but does not start a VM with disabled dynamic memory when identical values for startup, minimum and maximum memory are specified' { + Set-TargetResource -Name 'NewVM' @testParams -StartupMemory 4GB -MinimumMemory 4GB -MaximumMemory 4GB + Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Set-VMMemory -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It + } + + It 'Creates but does not start a VM with enabled dynamic memory because a MinimumMemory value is specified' { + Set-TargetResource -Name 'NewVM' @testParams -MinimumMemory 512MB + Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Set-VMMemory -Exactly -Times 0 -Scope It + Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It + } + + It 'Creates but does not start a VM with enabled dynamic memory because a MaximumMemory value is specified' { + Set-TargetResource -Name 'NewVM' @testParams -MaximumMemory 16GB + Assert-MockCalled -CommandName New-VM -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Set-VM -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName Set-VMMemory -Exactly -Times 0 -Scope It + Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It + } + + It 'Does not change VM state when VM "State" = "Running" and requested "State" = "Running"' { + Set-TargetResource -Name 'RunningVM' -State Running @testParams + Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It + } + + It 'Does not change VM state when VM "State" = "Off" and requested "State" = "Off"' { + Set-TargetResource -Name 'StoppedVM' -State Off @testParams + Assert-MockCalled -CommandName Set-VMState -Exactly -Times 0 -Scope It + } + + It 'Changes VM state when existing VM "State" = "Off" and requested "State" = "Running"' { + Set-TargetResource -Name 'StoppedVM' -State Running @testParams + Assert-MockCalled -CommandName Set-VMState -Exactly -Times 1 -Scope It + } + + It 'Changes VM state when existing VM "State" = "Running" and requested "State" = "Off"' { + Set-TargetResource -Name 'RunningVM' -State Off @testParams + Assert-MockCalled -CommandName Set-VMState -Exactly -Times 1 -Scope It + } + + It 'Creates a generation 1 VM by default/when not explicitly specified' { + Set-TargetResource -Name 'NewVM' @testParams + Assert-MockCalled -CommandName New-VM -ParameterFilter { $Generation -eq 1 } -Scope It + } + + It 'Creates a generation 1 VM when explicitly specified' { + Set-TargetResource -Name 'NewVM' -Generation 1 @testParams + Assert-MockCalled -CommandName New-VM -ParameterFilter { $Generation -eq 1 } -Scope It + } + + It 'Creates a generation 2 VM when explicitly specified' { + Set-TargetResource -Name 'NewVM' -Generation 2 @testParams + Assert-MockCalled -CommandName New-VM -ParameterFilter { $Generation -eq 2 } -Scope It + } + + It 'Calls "Add-VMNetworkAdapter" for each NIC when creating a new VM' { + Mock -CommandName Add-VMNetworkAdapter + Set-TargetResource -Name 'NewVM' @testParams -SwitchName 'Switch1', 'Switch2' + # The first NIC is assigned during the VM creation + Assert-MockCalled -CommandName Add-VMNetworkAdapter -Exactly 1 -Scope It + } + + It 'Calls "Connect-VMNetworkAdapter" for each existing NIC when updating an existing VM' { + Mock -CommandName Connect-VMNetworkAdapter + Set-TargetResource -Name 'StoppedVM' @testParams -SwitchName 'Switch1', 'Switch2' + # The first NIC is assigned during the VM creation + Assert-MockCalled -CommandName Connect-VMNetworkAdapter -Exactly 2 -Scope It + } + + It 'Calls "Add-VMNetworkAdapter" for each missing NIC when updating an existing VM' { + Mock -CommandName Connect-VMNetworkAdapter + Mock -CommandName Add-VMNetworkAdapter + Set-TargetResource -Name 'StoppedVM' @testParams -SwitchName 'Switch1', 'Switch2', 'Switch3' + # The first NIC is assigned during the VM creation + Assert-MockCalled -CommandName Connect-VMNetworkAdapter -Exactly 2 -Scope It + Assert-MockCalled -CommandName Add-VMNetworkAdapter -Exactly 1 -Scope It + } + + It 'Does not change switch assignments if no switch assignments are specified' { + Mock -CommandName Connect-VMNetworkAdapter + Set-TargetResource -Name 'StoppedVM' @testParams + Assert-MockCalled -CommandName Connect-VMNetworkAdapter -Exactly 0 -Scope It + } + + It 'Does not change NIC assignments if the switch assisgnments are correct' { + Mock -CommandName Set-VMNetworkAdapter + Set-TargetResource -Name 'StoppedVM' @testParams -SwitchName $stubNIC1.SwitchName, $stubNIC2.SwitchName + Assert-MockCalled -CommandName Set-VMNetworkAdapter -Exactly 0 -Scope It + } + + It 'Errors when updating MAC addresses on a running VM and "RestartIfNeeded" = "$false"' { + { Set-TargetResource -Name 'RunningVM' @testParams -MACAddress 'AABBCCDDEEFE', 'AABBCCDDEEFF' -ErrorAction Stop } | Should -Throw + } + + It 'Does not change MAC addresses if no MAC addresses assignments are specified' { + Mock -CommandName Set-VMNetworkAdapter -ParameterFilter { $StaticMacAddress -ne $null } + Set-TargetResource -Name 'StoppedVM' @testParams + Assert-MockCalled -CommandName Set-VMNetworkAdapter -ParameterFilter { $StaticMacAddress -ne $null } -Exactly 0 -Scope It + } + + It 'Calls "Set-VMNetworkAdapter" for each MAC address on a stopped VM' { + Mock -CommandName Set-VMNetworkAdapter + Set-TargetResource -Name 'StoppedVM' @testParams -MACAddress 'AABBCCDDEEFE', 'AABBCCDDEEFF' + # The first NIC is assigned during the VM creation + Assert-MockCalled -CommandName Set-VMNetworkAdapter -Exactly 2 -Scope It + } + + It 'Does not change Secure Boot call "Set-VMProperty" when creating a generation 1 VM' { + Mock -CommandName Set-VMProperty + Set-TargetResource -Name 'RunningVM' @testParams + Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 0 -Scope It + } + + It 'Does call "Set-VMProperty" when creating a generation 2 VM' { + Mock -CommandName Test-VMSecureBoot -MockWith { return $true } + Mock -CommandName Set-VMProperty + Set-TargetResource -Name 'RunningVM' -Generation 2 -SecureBoot $false @testParams + Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 1 -Scope It + } + + It 'Does not change Secure Boot for generation 1 VM' { + Mock -CommandName Test-VMSecureBoot -MockWith { return $true } + Mock -CommandName Set-VMProperty + Set-TargetResource -Name 'StoppedVM' -SecureBoot $true @testParams + Set-TargetResource -Name 'StoppedVM' -SecureBoot $false @testParams + Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 0 -Scope It + } + + It 'Does not change Secure Boot for generation 2 VM with VM "SecureBoot" match' { + Mock -CommandName Test-VMSecureBoot -MockWith { return $true } + Mock -CommandName Set-VMProperty + Set-TargetResource -Name 'StoppedVM' -SecureBoot $true -Generation 2 @testParams + Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 0 -Scope It + } + + It 'Does change Secure Boot for generation 2 VM with VM "SecureBoot" mismatch' { + Mock -CommandName Test-VMSecureBoot -MockWith { return $false } + Mock -CommandName Set-VMProperty + Set-TargetResource -Name 'StoppedVM' -SecureBoot $true -Generation 2 @testParams + Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { $VMCommand -eq 'Set-VMFirmware' } -Exactly 1 -Scope It + } + + It 'Does call "Enable-VMIntegrationService" when "EnableGuestService" = "$true"' { + Mock -CommandName Enable-VMIntegrationService + Set-TargetResource -Name 'RunningVM' -EnableGuestService $true @testParams + Assert-MockCalled -CommandName Enable-VMIntegrationService -Exactly -Times 1 -Scope It + } + + It 'Does call "Disable-VMIntegrationService" when "Guest Service Interface" = "Enabled" and "EnableGuestService" = "$false" specified' { + Mock -CommandName Disable-VMIntegrationService + Mock -CommandName Get-VMIntegrationService -MockWith { + $guestServiceInterface = [Microsoft.HyperV.PowerShell.VMIntegrationComponent]::CreateTypeInstance() + $guestServiceInterface.Enabled = $true + $guestServiceInterface.Id = $stubGuestServiceInterfaceId + + return $guestServiceInterface + } + + Set-TargetResource -Name 'RunningVM' -EnableGuestService $false @testParams + Assert-MockCalled -CommandName Disable-VMIntegrationService -Exactly -Times 1 -Scope It + } + + Mock -CommandName Get-Command -ParameterFilter { $Name -eq 'Set-VM' -and $Module -eq 'Hyper-V' } -MockWith { + [pscustomobject]@{ + parameters = @{ + # Does not contain parameter AutomaticCheckpointsEnabled + } + } + } + It 'throws when AutomaticCheckpointsEnabled is configured but not supported' { + { Set-TargetResource -Name 'VMAutomaticCheckpointsUnsupported' -AutomaticCheckpointsEnabled $true @testParams } | Should -Throw + } + It 'Does not call "Set-VM" when "AutomaticCheckpointsEnabled" is unsupported and unspecified' { + Set-TargetResource -Name 'VMAutomaticCheckpointsUnsupported' @testParams + Assert-MockCalled -CommandName Set-VM -Exactly -Times 0 -Scope It + } + + Mock -CommandName Get-Command -ParameterFilter { $Name -eq 'Set-VM' -and $Module -eq 'Hyper-V' } -MockWith { + [pscustomobject]@{ + parameters = @{ + 'AutomaticCheckpointsEnabled' = '' + } + } + } + $AutomaticCheckpointsEnabledTestCases = @( + @{ + VMName = 'VMWithAutomaticCheckpoints' + SetAutomaticCheckpointsEnabled = $true + Assert = 'Does not call "Set-VM"' + Times = 0 + }, + @{ + VMName = 'VMWithoutAutomaticCheckpoints' + SetAutomaticCheckpointsEnabled = $false + Assert = 'Does not call "Set-VM"' + Times = 0 + }, + @{ + VMName = 'VMWithAutomaticCheckpoints' + SetAutomaticCheckpointsEnabled = $false + Assert = 'Does call "Set-VM"' + Times = 1 + }, + @{ + VMName = 'VMWithoutAutomaticCheckpoints' + SetAutomaticCheckpointsEnabled = $true + Assert = 'Does call "Set-VM"' + Times = 1 + } + ) + It ' on VM when "AutomaticCheckpointsEnabled" is set to ""' -TestCases $AutomaticCheckpointsEnabledTestCases { + param + ( + $VMName, + $SetAutomaticCheckpointsEnabled, + $Times + ) + + Set-TargetResource -Name $VMName -AutomaticCheckpointsEnabled $SetAutomaticCheckpointsEnabled @testParams + Assert-MockCalled -CommandName Set-VM -ParameterFilter { $Name -eq $VMName -and $AutomaticCheckpointsEnabled -eq $SetAutomaticCheckpointsEnabled } -Exactly -Times $Times -Scope It + } + It 'Disables dynamic memory of RuningVM if only StartupMemory specified' { + Mock -CommandName Set-VMProperty + Set-TargetResource -Name 'RunningVM' -StartupMemory 4GB @testParams + Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { + $VMCommand -eq 'Set-VM' -and + ($ChangeProperty.StaticMemory -eq $true) -and + ($ChangeProperty.DynamicMemory -eq $false) + } -Exactly -Times 1 -Scope It + } + + It 'Disables dynamic memory of RunningVM if StartupMemory, MinimumMemory and MaximumMemory are specified with the same values' { + Mock -CommandName Set-VMProperty + Set-TargetResource -Name 'RunningVM' -StartupMemory 4GB -MinimumMemory 4GB -MaximumMemory 4GB @testParams + Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { + $VMCommand -eq 'Set-VM' -and + ($ChangeProperty.StaticMemory -eq $true) -and + ($ChangeProperty.DynamicMemory -eq $false) + } -Exactly -Times 1 -Scope It + } + + It 'Enables dynamic memory of RuningVM if MinimumMemory is specified ' { + Mock -CommandName Set-VMProperty + Set-TargetResource -Name 'RunningVM' -MinimumMemory 4GB @testParams + Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { + $VMCommand -eq 'Set-VM' -and + ($ChangeProperty.StaticMemory -eq $false) -and + ($ChangeProperty.DynamicMemory -eq $true) + } -Exactly -Times 1 -Scope It + } + + It 'Enables dynamic memory of RuningVM if MaximumMemory is specified ' { + Mock -CommandName Set-VMProperty + Set-TargetResource -Name 'RunningVM' -MaximumMemory 4GB @testParams + Assert-MockCalled -CommandName Set-VMProperty -ParameterFilter { + $VMCommand -eq 'Set-VM' -and + ($ChangeProperty.StaticMemory -eq $false) -and + ($ChangeProperty.DynamicMemory -eq $true) + } -Exactly -Times 1 -Scope It + } + + It 'throws when Hyper-V Tools are not installed' { + Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } + { Set-TargetResource -Name 'RunningVM' @testParams } | Should -Throw + } + } #end context Validates Set-TargetResource Method + + Context 'Validates Test-VMSecureBoot Method' { + BeforeAll { + Mock -CommandName Get-VM -MockWith { + $stubVM = [Microsoft.HyperV.PowerShell.VirtualMachine]::CreateTypeInstance() + $stubVM.Name = 'NewVM' + $stubVM.Path = $StubVMConfig.FullPath + $stubVM.Generation = $Generation + $stubVM.ID = $mockVmGuid + $stubVM.State = 'Off' + + return $stubVM + } + } + + It 'Returns $true when "SecureBoot" = "On"' { + Mock -CommandName Get-VMFirmware -MockWith { + return [PSCustomObject] @{ + SecureBoot = 'On' + } + } + + Test-VMSecureBoot -Name 'TestVM' | Should -Be $true + } + + It 'Returns $false when "SecureBoot" = "Off"' { + Mock -CommandName Get-VMFirmware -MockWith { + return [PSCustomObject] @{ + SecureBoot = 'Off' + } + } + + Test-VMSecureBoot -Name 'TestVM' | Should -Be $false + } + + } #end context Validates Test-VMSecureBoot Method + + Context 'Validates Get-VhdHierarchy Method' { + It 'Does not throw with null parent path (#52)' { + # Must use a different file extension to ensure existing mocks Get-VhdHierarchy or not called + $fakeVhdPath = 'BaseVhd.avhdx' + + Mock -CommandName Get-VHD -ParameterFilter { $Path -eq $fakeVhdPath } -MockWith { + return [PSCustomObject] @{ + Path = $fakeVhdPath + ParentPath = $null + } + } + + { Get-VhdHierarchy -VhdPath $fakeVhdPath } | Should -Not -throw + } + + } #end context validates Get-VhdHierarchy + } #end describe xVMHyper-V + } #end inmodulescope +} +finally +{ + Invoke-TestCleanup +} diff --git a/tests/Unit/DSC_VMNetworkAdapter.Tests.ps1 b/tests/Unit/DSC_VMNetworkAdapter.Tests.ps1 index b07d883..e9fa23a 100644 --- a/tests/Unit/DSC_VMNetworkAdapter.Tests.ps1 +++ b/tests/Unit/DSC_VMNetworkAdapter.Tests.ps1 @@ -1,352 +1,352 @@ -# $script:dscModuleName = 'HyperVDsc' -# $script:dscResourceName = 'DSC_VMNetworkAdapter' - -# function Invoke-TestSetup -# { -# try -# { -# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' -# } -# catch [System.IO.FileNotFoundException] -# { -# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' -# } - -# $script:testEnvironment = Initialize-TestEnvironment ` -# -DSCModuleName $script:dscModuleName ` -# -DSCResourceName $script:dscResourceName ` -# -ResourceType 'Mof' ` -# -TestType 'Unit' - -# # Import the stub functions. -# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -# } - -# function Invoke-TestCleanup -# { -# Restore-TestEnvironment -TestEnvironment $script:testEnvironment -# } - -# Invoke-TestSetup - -# try -# { -# InModuleScope $script:dscResourceName { -# # Create the Mock -CommandName Objects that will be used for running tests -# $MockHostAdapter = [PSCustomObject] @{ -# Id = 'HostManagement1' -# Name = 'Management' -# SwitchName = 'HostSwitch' -# VMName = 'ManagementOS' -# } - -# $propertiesStatic = @{ -# DHCPEnabled = $false -# IpAddress = "192.168.0.1" -# Subnet = "255.255.255.0" -# } - -# $networkSettingsStatic = New-CimInstance -ClassName VMNetworkAdapterNetworkSettings -Property $propertiesStatic -Namespace root/microsoft/windows/desiredstateconfiguration -ClientOnly - -# $TestAdapter = [PSObject]@{ -# Id = $MockHostAdapter.Id -# Name = $MockHostAdapter.Name -# SwitchName = $MockHostAdapter.SwitchName -# VMName = $MockHostAdapter.VMName -# } - -# $MockAdapter = [Microsoft.HyperV.PowerShell.VMNetworkAdapterBase]::CreateTypeInstance() -# $MockAdapter.Name = $MockHostAdapter.Name -# $MockAdapter.SwitchName = $MockHostAdapter.SwitchName -# $MockAdapter.VMName = $MockHostAdapter.VMName -# $MockAdapter.IsManagementOs = $true -# $MockAdapter.MacAddress = '14FEB5C6CE98' - -# $MockAdapterVlanUntagged = [PSObject]@{ -# OperationMode = 'Untagged' -# } - -# $MockAdapterVlanTagged = [PSObject]@{ -# OperationMode = 'Access' -# AccessVlanId = '1' -# } - -# Describe 'DSC_VMNetworkAdapter\Get-TargetResource' { -# Context 'NetAdapter does not exist' { -# Mock -CommandName Get-VMNetworkAdapter -# Mock -CommandName Get-VMNetworkAdapterVlan -# It 'should return ensure as absent' { -# $Result = Get-TargetResource ` -# @TestAdapter -# $Result.Ensure | Should -Be 'Absent' -# } -# It 'should call the expected mocks' { -# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 -# Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 0 -# } -# } - -# Context 'NetAdapter with untagged VLAN exists' { -# Mock -CommandName Get-VMNetworkAdapter -MockWith { -# $MockAdapter -# } - -# Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { -# $MockAdapterVlanUntagged -# } -# Mock -CommandName Get-NetworkInformation -MockWith { -# return @{ -# IpAddress = '10.10.10.10' -# Subnet = '255.255.255.0' -# DefaultGateway = '10.10.10.1' -# DnsServer = @( '10.10.10.1' ) -# } -# } - -# It 'should return adapter properties' { -# $Result = Get-TargetResource @TestAdapter -# $Result.Ensure | Should -Be 'Present' -# $Result.Name | Should -Be $TestAdapter.Name -# $Result.SwitchName | Should -Be $TestAdapter.SwitchName -# $Result.VMName | Should -Be 'ManagementOS' -# $Result.Id | Should -Be $TestAdapter.Id -# $Result.VlanId | Should -BeNullOrEmpty -# $Result.NetworkSetting | Should -Not -BeNullOrEmpty -# } -# It 'should call the expected mocks' { -# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 -# Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 -# } -# } - -# Context 'NetAdapter with tagged VLAN exists' { -# Mock -CommandName Get-VMNetworkAdapter -MockWith { -# $MockAdapter -# } - -# Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { -# $MockAdapterVlanTagged -# } - -# Mock -CommandName Get-NetworkInformation -MockWith { -# return @{ -# IpAddress = '10.10.10.10' -# Subnet = '255.255.255.0' -# DefaultGateway = '10.10.10.1' -# DnsServer = @( '10.10.10.1', '10.10.10.2' ) -# } -# } - -# It 'should return adapter properties' { -# $Result = Get-TargetResource @TestAdapter -# $Result.Ensure | Should -Be 'Present' -# $Result.Name | Should -Be $TestAdapter.Name -# $Result.SwitchName | Should -Be $TestAdapter.SwitchName -# $Result.VMName | Should -Be 'ManagementOS' -# $Result.Id | Should -Be $TestAdapter.Id -# $Result.VlanId | Should -Be '1' -# } -# It 'should call the expected mocks' { -# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 -# Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 -# } -# } -# } - -# Describe 'DSC_VMNetworkAdapter\Set-TargetResource' { -# $newAdapter = [PSObject]@{ -# Id = 'UniqueString' -# Name = $TestAdapter.Name -# SwitchName = $TestAdapter.SwitchName -# VMName = 'VMName' -# NetworkSetting = $networkSettingsStatic -# Ensure = 'Present' -# } - -# Context 'Adapter does not exist but should' { -# Mock -CommandName Get-VMNetworkAdapter -# Mock -CommandName Get-VMNetworkAdapterVlan -# Mock -CommandName Add-VMNetworkAdapter -MockWith { -# $MockAdapter -# } -# Mock -CommandName Remove-VMNetworkAdapter -# Mock -CommandName Set-VMNetworkAdapterVlan -# Mock -CommandName Set-NetworkInformation - -# It 'should not throw error' { -# { -# Set-TargetResource @newAdapter -# } | Should -Not -throw -# } - -# It 'should call expected Mocks' { -# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 -# Assert-MockCalled -CommandName Set-VMNetworkAdapterVlan -Exactly 0 -# Assert-MockCalled -commandName Add-VMNetworkAdapter -Exactly 1 -# Assert-MockCalled -commandName Remove-VMNetworkAdapter -Exactly 0 -# Assert-MockCalled -CommandName Set-NetworkInformation -Exactly 1 -# } -# } - -# Context 'Adapter exists but should not exist' { -# Mock -CommandName Get-VMNetworkAdapter -# Mock -CommandName Add-VMNetworkAdapter -# Mock -CommandName Remove-VMNetworkAdapter -# Mock -CommandName Set-VMNetworkAdapterVlan - -# It 'should not throw error' { -# { -# $updateAdapter = $newAdapter.Clone() -# $updateAdapter.Ensure = 'Absent' -# Set-TargetResource @updateAdapter -# } | Should -Not -throw -# } -# It 'should call expected Mocks' { -# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 -# Assert-MockCalled -commandName Add-VMNetworkAdapter -Exactly 0 -# Assert-MockCalled -commandName Remove-VMNetworkAdapter -Exactly 1 -# Assert-MockCalled -CommandName Set-VMNetworkAdapterVlan -Exactly 0 -# } -# } -# } - -# Describe 'DSC_VMNetworkAdapter\Test-TargetResource' { -# $newAdapter = [PSObject]@{ -# Id = 'UniqueString' -# Name = $TestAdapter.Name -# SwitchName = $TestAdapter.SwitchName -# VMName = 'ManagementOS' -# Ensure = 'Present' -# } - -# Context 'Adapter does not exist but should' { -# Mock -CommandName Get-VMNetworkAdapter -# Mock -CommandName Get-VMNetworkAdapterVlan - -# It 'should return false' { -# Test-TargetResource @newAdapter | Should -Be $false -# } -# It 'should call expected Mocks' { -# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 -# } -# } - -# Context 'Adapter exists but should not exist' { -# Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } - -# It 'should return $false' { -# $updateAdapter = $newAdapter.Clone() -# $updateAdapter.Ensure = 'Absent' -# Test-TargetResource @updateAdapter | Should -Be $false -# } -# It 'should call expected Mocks' { -# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 -# } -# } - -# Context 'Adapter exists and no action needed without Vlan tag' { -# Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } - -# It 'should return true' { -# $updateAdapter = $newAdapter.Clone() -# Test-TargetResource @updateAdapter | Should -Be $true -# } -# It 'should call expected Mocks' { -# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 -# } -# } - -# Context 'Adapter exists and no action needed with Vlan tag' { -# Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } -# Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { $MockAdapterVlanTagged } -# Mock -CommandName Get-NetworkInformation - -# It 'should return true' { -# $updateAdapter = $newAdapter.Clone() -# $updateAdapter.VMName = "VMName" -# $updateAdapter.MacAddress = '14FEB5C6CE98' -# $updateAdapter.VlanId = '1' -# Test-TargetResource @updateAdapter | Should -Be $true -# } -# It 'should call expected Mocks' { -# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 -# Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 -# } -# } - -# Context 'Adapter exists but Vlan is not tagged' { -# Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } -# Mock -CommandName Get-VMNetworkAdapterVlan -# Mock -CommandName Get-NetworkInformation - -# It 'should return false' { -# $updateAdapter = $newAdapter.Clone() -# $updateAdapter.VMName = "VMName" -# $updateAdapter.MacAddress = '14FEB5C6CE98' -# $updateAdapter.VlanId = '1' -# Test-TargetResource @updateAdapter | Should -Be $false -# } -# It 'should call expected Mocks' { -# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 -# Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 -# } -# } - -# Context 'Adapter exists but Vlan tag is wrong' { -# Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } -# Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { $MockAdapterVlanTagged } -# Mock -CommandName Get-NetworkInformation - -# It 'should return false' { -# $updateAdapter = $newAdapter.Clone() -# $updateAdapter.VMName = "VMName" -# $updateAdapter.MacAddress = '14FEB5C6CE98' -# $updateAdapter.VlanId = '2' -# Test-TargetResource @updateAdapter | Should -Be $false -# } -# It 'should call expected Mocks' { -# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 -# Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 -# } -# } - -# Context 'Adapter does not exist and no action needed' { -# Mock -CommandName Get-VMNetworkAdapter - -# It 'should return true' { -# $updateAdapter = $newAdapter.Clone() -# $updateAdapter.Ensure = 'Absent' -# Test-TargetResource @updateAdapter | Should -Be $true -# } -# It 'should call expected Mocks' { -# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 -# } -# } - -# Context 'Adapter exists and network settings are not specified' { -# Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } -# Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { $MockAdapterVlanTagged } -# Mock -CommandName Get-NetworkInformation -MockWith { -# @{ DHCPEnabled = $false } -# } - -# It 'should return false' { -# $updateAdapter = $newAdapter.Clone() -# $updateAdapter.VMName = "VMName" -# $updateAdapter.MacAddress = '14FEB5C6CE98' -# Test-TargetResource @updateAdapter | Should -Be $false -# } -# It 'should call expected Mocks' { -# Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 -# Assert-MockCalled -commandName Get-NetworkInformation -Exactly 0 -# } -# } -# } - -# } -# #endregion -# } -# finally -# { -# Invoke-TestCleanup -# } +$script:dscModuleName = 'HyperVDsc' +$script:dscResourceName = 'DSC_VMNetworkAdapter' + +function Invoke-TestSetup +{ + try + { + Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + } + + $script:testEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:dscModuleName ` + -DSCResourceName $script:dscResourceName ` + -ResourceType 'Mof' ` + -TestType 'Unit' + + # Import the stub functions. + Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +} + +function Invoke-TestCleanup +{ + Restore-TestEnvironment -TestEnvironment $script:testEnvironment +} + +Invoke-TestSetup + +try +{ + InModuleScope $script:dscResourceName { + # Create the Mock -CommandName Objects that will be used for running tests + $MockHostAdapter = [PSCustomObject] @{ + Id = 'HostManagement1' + Name = 'Management' + SwitchName = 'HostSwitch' + VMName = 'ManagementOS' + } + + $propertiesStatic = @{ + DHCPEnabled = $false + IpAddress = "192.168.0.1" + Subnet = "255.255.255.0" + } + + $networkSettingsStatic = New-CimInstance -ClassName VMNetworkAdapterNetworkSettings -Property $propertiesStatic -Namespace root/microsoft/windows/desiredstateconfiguration -ClientOnly + + $TestAdapter = [PSObject]@{ + Id = $MockHostAdapter.Id + Name = $MockHostAdapter.Name + SwitchName = $MockHostAdapter.SwitchName + VMName = $MockHostAdapter.VMName + } + + $MockAdapter = [Microsoft.HyperV.PowerShell.VMNetworkAdapterBase]::CreateTypeInstance() + $MockAdapter.Name = $MockHostAdapter.Name + $MockAdapter.SwitchName = $MockHostAdapter.SwitchName + $MockAdapter.VMName = $MockHostAdapter.VMName + $MockAdapter.IsManagementOs = $true + $MockAdapter.MacAddress = '14FEB5C6CE98' + + $MockAdapterVlanUntagged = [PSObject]@{ + OperationMode = 'Untagged' + } + + $MockAdapterVlanTagged = [PSObject]@{ + OperationMode = 'Access' + AccessVlanId = '1' + } + + Describe 'DSC_VMNetworkAdapter\Get-TargetResource' { + Context 'NetAdapter does not exist' { + Mock -CommandName Get-VMNetworkAdapter + Mock -CommandName Get-VMNetworkAdapterVlan + It 'should return ensure as absent' { + $Result = Get-TargetResource ` + @TestAdapter + $Result.Ensure | Should -Be 'Absent' + } + It 'should call the expected mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 0 + } + } + + Context 'NetAdapter with untagged VLAN exists' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { + $MockAdapter + } + + Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { + $MockAdapterVlanUntagged + } + Mock -CommandName Get-NetworkInformation -MockWith { + return @{ + IpAddress = '10.10.10.10' + Subnet = '255.255.255.0' + DefaultGateway = '10.10.10.1' + DnsServer = @( '10.10.10.1' ) + } + } + + It 'should return adapter properties' { + $Result = Get-TargetResource @TestAdapter + $Result.Ensure | Should -Be 'Present' + $Result.Name | Should -Be $TestAdapter.Name + $Result.SwitchName | Should -Be $TestAdapter.SwitchName + $Result.VMName | Should -Be 'ManagementOS' + $Result.Id | Should -Be $TestAdapter.Id + $Result.VlanId | Should -BeNullOrEmpty + $Result.NetworkSetting | Should -Not -BeNullOrEmpty + } + It 'should call the expected mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 + } + } + + Context 'NetAdapter with tagged VLAN exists' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { + $MockAdapter + } + + Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { + $MockAdapterVlanTagged + } + + Mock -CommandName Get-NetworkInformation -MockWith { + return @{ + IpAddress = '10.10.10.10' + Subnet = '255.255.255.0' + DefaultGateway = '10.10.10.1' + DnsServer = @( '10.10.10.1', '10.10.10.2' ) + } + } + + It 'should return adapter properties' { + $Result = Get-TargetResource @TestAdapter + $Result.Ensure | Should -Be 'Present' + $Result.Name | Should -Be $TestAdapter.Name + $Result.SwitchName | Should -Be $TestAdapter.SwitchName + $Result.VMName | Should -Be 'ManagementOS' + $Result.Id | Should -Be $TestAdapter.Id + $Result.VlanId | Should -Be '1' + } + It 'should call the expected mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 + } + } + } + + Describe 'DSC_VMNetworkAdapter\Set-TargetResource' { + $newAdapter = [PSObject]@{ + Id = 'UniqueString' + Name = $TestAdapter.Name + SwitchName = $TestAdapter.SwitchName + VMName = 'VMName' + NetworkSetting = $networkSettingsStatic + Ensure = 'Present' + } + + Context 'Adapter does not exist but should' { + Mock -CommandName Get-VMNetworkAdapter + Mock -CommandName Get-VMNetworkAdapterVlan + Mock -CommandName Add-VMNetworkAdapter -MockWith { + $MockAdapter + } + Mock -CommandName Remove-VMNetworkAdapter + Mock -CommandName Set-VMNetworkAdapterVlan + Mock -CommandName Set-NetworkInformation + + It 'should not throw error' { + { + Set-TargetResource @newAdapter + } | Should -Not -throw + } + + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + Assert-MockCalled -CommandName Set-VMNetworkAdapterVlan -Exactly 0 + Assert-MockCalled -commandName Add-VMNetworkAdapter -Exactly 1 + Assert-MockCalled -commandName Remove-VMNetworkAdapter -Exactly 0 + Assert-MockCalled -CommandName Set-NetworkInformation -Exactly 1 + } + } + + Context 'Adapter exists but should not exist' { + Mock -CommandName Get-VMNetworkAdapter + Mock -CommandName Add-VMNetworkAdapter + Mock -CommandName Remove-VMNetworkAdapter + Mock -CommandName Set-VMNetworkAdapterVlan + + It 'should not throw error' { + { + $updateAdapter = $newAdapter.Clone() + $updateAdapter.Ensure = 'Absent' + Set-TargetResource @updateAdapter + } | Should -Not -throw + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + Assert-MockCalled -commandName Add-VMNetworkAdapter -Exactly 0 + Assert-MockCalled -commandName Remove-VMNetworkAdapter -Exactly 1 + Assert-MockCalled -CommandName Set-VMNetworkAdapterVlan -Exactly 0 + } + } + } + + Describe 'DSC_VMNetworkAdapter\Test-TargetResource' { + $newAdapter = [PSObject]@{ + Id = 'UniqueString' + Name = $TestAdapter.Name + SwitchName = $TestAdapter.SwitchName + VMName = 'ManagementOS' + Ensure = 'Present' + } + + Context 'Adapter does not exist but should' { + Mock -CommandName Get-VMNetworkAdapter + Mock -CommandName Get-VMNetworkAdapterVlan + + It 'should return false' { + Test-TargetResource @newAdapter | Should -Be $false + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + } + } + + Context 'Adapter exists but should not exist' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } + + It 'should return $false' { + $updateAdapter = $newAdapter.Clone() + $updateAdapter.Ensure = 'Absent' + Test-TargetResource @updateAdapter | Should -Be $false + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + } + } + + Context 'Adapter exists and no action needed without Vlan tag' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } + + It 'should return true' { + $updateAdapter = $newAdapter.Clone() + Test-TargetResource @updateAdapter | Should -Be $true + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + } + } + + Context 'Adapter exists and no action needed with Vlan tag' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } + Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { $MockAdapterVlanTagged } + Mock -CommandName Get-NetworkInformation + + It 'should return true' { + $updateAdapter = $newAdapter.Clone() + $updateAdapter.VMName = "VMName" + $updateAdapter.MacAddress = '14FEB5C6CE98' + $updateAdapter.VlanId = '1' + Test-TargetResource @updateAdapter | Should -Be $true + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 + } + } + + Context 'Adapter exists but Vlan is not tagged' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } + Mock -CommandName Get-VMNetworkAdapterVlan + Mock -CommandName Get-NetworkInformation + + It 'should return false' { + $updateAdapter = $newAdapter.Clone() + $updateAdapter.VMName = "VMName" + $updateAdapter.MacAddress = '14FEB5C6CE98' + $updateAdapter.VlanId = '1' + Test-TargetResource @updateAdapter | Should -Be $false + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 + } + } + + Context 'Adapter exists but Vlan tag is wrong' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } + Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { $MockAdapterVlanTagged } + Mock -CommandName Get-NetworkInformation + + It 'should return false' { + $updateAdapter = $newAdapter.Clone() + $updateAdapter.VMName = "VMName" + $updateAdapter.MacAddress = '14FEB5C6CE98' + $updateAdapter.VlanId = '2' + Test-TargetResource @updateAdapter | Should -Be $false + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + Assert-MockCalled -commandName Get-VMNetworkAdapterVlan -Exactly 1 + } + } + + Context 'Adapter does not exist and no action needed' { + Mock -CommandName Get-VMNetworkAdapter + + It 'should return true' { + $updateAdapter = $newAdapter.Clone() + $updateAdapter.Ensure = 'Absent' + Test-TargetResource @updateAdapter | Should -Be $true + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + } + } + + Context 'Adapter exists and network settings are not specified' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } + Mock -CommandName Get-VMNetworkAdapterVlan -MockWith { $MockAdapterVlanTagged } + Mock -CommandName Get-NetworkInformation -MockWith { + @{ DHCPEnabled = $false } + } + + It 'should return false' { + $updateAdapter = $newAdapter.Clone() + $updateAdapter.VMName = "VMName" + $updateAdapter.MacAddress = '14FEB5C6CE98' + Test-TargetResource @updateAdapter | Should -Be $false + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + Assert-MockCalled -commandName Get-NetworkInformation -Exactly 0 + } + } + } + + } + #endregion +} +finally +{ + Invoke-TestCleanup +} diff --git a/tests/Unit/DSC_VMProcessor.Tests.ps1 b/tests/Unit/DSC_VMProcessor.Tests.ps1 index 354e4fa..f261477 100644 --- a/tests/Unit/DSC_VMProcessor.Tests.ps1 +++ b/tests/Unit/DSC_VMProcessor.Tests.ps1 @@ -1,294 +1,294 @@ -# $script:dscModuleName = 'HyperVDsc' -# $script:dscResourceName = 'DSC_VMProcessor' +$script:dscModuleName = 'HyperVDsc' +$script:dscResourceName = 'DSC_VMProcessor' -# function Invoke-TestSetup -# { -# try -# { -# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' -# } -# catch [System.IO.FileNotFoundException] -# { -# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' -# } +function Invoke-TestSetup +{ + try + { + Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + } -# $script:testEnvironment = Initialize-TestEnvironment ` -# -DSCModuleName $script:dscModuleName ` -# -DSCResourceName $script:dscResourceName ` -# -ResourceType 'Mof' ` -# -TestType 'Unit' + $script:testEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:dscModuleName ` + -DSCResourceName $script:dscResourceName ` + -ResourceType 'Mof' ` + -TestType 'Unit' -# # Import the stub functions. -# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -# } - -# function Invoke-TestCleanup -# { -# Restore-TestEnvironment -TestEnvironment $script:testEnvironment -# } - -# Invoke-TestSetup - -# try -# { -# InModuleScope $script:dscResourceName { - -# $testVMName = 'UnitTestVM' -# $testResourcePoolName = 'Unit Test Resource Pool' - -# Describe 'DSC_VMProcessor\Get-TargetResource' { - -# $fakeVMProcessor = @{ -# EnableHostResourceProtection = $true -# } - -# # Guard mocks -# Mock -CommandName Assert-Module - -# It 'Should return a [System.Collections.Hashtable] object type' { -# Mock -CommandName Get-VMProcessor { return $fakeVMProcessor } - -# $result = Get-TargetResource -VMName $testVMName - -# $result -is [System.Collections.Hashtable] | Should -Be $true -# } - -# It 'Should assert Hyper-V module is installed' { -# Mock -CommandName Assert-Module -# Mock -CommandName Get-VMProcessor { return $fakeVMProcessor } - -# $null = Get-TargetResource -VMName $testVMName - -# Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It -# } - -# It 'Should throw when VM processor is not found' { -# Mock -CommandName Get-Module { return $true } -# Mock -CommandName Get-VMProcessor { Write-Error 'Not Found' } -# { $null = Get-TargetResource -VMName $testVMName } | Should -Throw 'Not Found' -# } -# } # descrive Get-TargetResource - -# Describe 'DSC_VMProcessor\Test-TargetResource' { - -# # Guard mocks -# Mock -CommandName Assert-Module -# Mock -CommandName Assert-TargetResourceParameter - -# $fakeTargetResource = @{ -# VMName = $testVMName -# EnableHostResourceProtection = $true -# ExposeVirtualizationExtensions = $true -# HwThreadCountPerCore = 1 -# Maximum = 99 -# MaximumCountPerNumaNode = 4 -# MaximumCountPerNumaSocket = 1 -# RelativeWeight = 99 -# Reserve = 0 -# ResourcePoolName = $testResourcePoolName -# CompatibilityForMigrationEnabled = $false -# CompatibilityForOlderOperatingSystemsEnabled = $false -# } - -# It 'Should return a [System.Boolean] object type' { -# Mock -CommandName Get-TargetResource { return $fakeTargetResource } - -# $result = Test-TargetResource -VMName $testVMName - -# $result -is [System.Boolean] | Should -Be $true -# } - -# It 'Should assert Hyper-V module is installed' { -# Mock -CommandName Get-VMProcessor { return $fakeVMProcessor } - -# $null = Test-TargetResource -VMName $testVMName - -# Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It -# } - -# It 'Should assert parameter values are valid' { -# Mock -CommandName Get-VMProcessor { return $fakeVMProcessor } - -# $null = Test-TargetResource -VMName $testVMName - -# Assert-MockCalled -CommandName Assert-TargetResourceParameter -Scope It -# } - -# $parameterNames = @( -# 'EnableHostResourceProtection', -# 'ExposeVirtualizationExtensions', -# 'HwThreadCountPerCore', -# 'Maximum', -# 'MaximumCountPerNumaNode', -# 'MaximumCountPerNumaSocket', -# 'RelativeWeight', -# 'Reserve', -# 'ResourcePoolName', -# 'CompatibilityForMigrationEnabled', -# 'CompatibilityForOlderOperatingSystemsEnabled' -# ) - -# # Test each individual parameter value separately -# foreach ($parameterName in $parameterNames) -# { -# $parameterValue = $fakeTargetResource[$parameterName] -# $testTargetResourceParams = @{ -# VMName = $testVMName -# } - -# # Pass value verbatim so it should always pass first -# It "Should pass when parameter '$parameterName' is correct" { -# $testTargetResourceParams[$parameterName] = $parameterValue - -# $result = Test-TargetResource @testTargetResourceParams - -# $result | Should -Be $true -# } - -# if ($parameterValue -is [System.Boolean]) -# { -# # Invert parameter value to cause a test failure -# $testTargetResourceParams[$parameterName] = -not $parameterValue -# } -# elseif ($parameterValue -is [System.String]) -# { -# # Repeat string to cause a test failure -# $testTargetResourceParams[$parameterName] = "$parameterValue$parameterValue" -# } -# elseif ($parameterValue -is [System.Int32] -or $parameterValue -is [System.Int64]) -# { -# # Add one to cause a test failure -# $testTargetResourceParams[$parameterName] = $parameterValue + 1 -# } - -# It "Should fail when parameter '$parameterName' is incorrect" { -# $result = Test-TargetResource @testTargetResourceParams - -# $result | Should -Be $false -# } -# } -# } # describe Test-TargetResource - -# Describe 'DSC_VMProcessor\Set-TargetResource' { -# # Guard mocks -# Mock -CommandName Assert-Module -# Mock -CommandName Assert-TargetResourceParameter -# Mock -CommandName Get-VM -# Mock -CommandName Set-VMProcessor -# Mock -CommandName Set-VMProperty - -# It 'Should assert Hyper-V module is installed' { -# $null = Set-TargetResource -VMName $testVMName - -# Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It -# } - -# It 'Should assert parameter values are valid' { -# $null = Set-TargetResource -VMName $testVMName - -# Assert-MockCalled -CommandName Assert-TargetResourceParameter -Scope It -# } - -# $restartRequiredParameters = @{ -# 'ExposeVirtualizationExtensions' = $false -# 'CompatibilityForMigrationEnabled' = $true -# 'CompatibilityForOlderOperatingSystemsEnabled' = $true -# 'HwThreadCountPerCore' = 2 -# 'MaximumCountPerNumaNode' = 2 -# 'MaximumCountPerNumaSocket' = 2 -# 'ResourcePoolName' = $testResourcePoolName -# } - -# foreach ($parameter in $restartRequiredParameters.GetEnumerator()) -# { -# $setTargetResourceParams = @{ -# VMName = $testVMName -# $parameter.Name = $parameter.Value -# } - -# It "Should not throw when VM is off, '$($parameter.Name)' is specified and 'RestartIfNeeded' is False" { -# Mock -CommandName Get-VM -MockWith { -# return @{ -# State = 'Off' -# } -# } - -# { Set-TargetResource @setTargetResourceParams } | Should -Not -throw -# } - -# It "Should throw when VM is running, '$($parameter.Name)' is specified and 'RestartIfNeeded' is False" { -# Mock -CommandName Get-VM { return @{ State = 'Running' } } - -# { Set-TargetResource @setTargetResourceParams } | Should -Throw -# } - -# It "Should shutdown VM when running, '$($parameter.Name)' is specified and 'RestartIfNeeded' is True" { -# Mock -CommandName Get-VM { return @{ State = 'Running' } } - -# Set-TargetResource @setTargetResourceParams -RestartIfNeeded $true - -# Assert-MockCalled -CommandName Set-VMProperty -Scope It -Exactly 1 -# } -# } - -# $noRestartRequiredParameters = @{ -# 'EnableHostResourceProtection' = $true -# 'Maximum' = 50 -# 'RelativeWeight' = 50 -# 'Reserve' = 50 -# } - -# foreach ($parameter in $noRestartRequiredParameters.GetEnumerator()) -# { -# $setTargetResourceParams = @{ -# VMName = $testVMName -# $parameter.Name = $parameter.Value -# } - -# It "Should not shutdown VM running and '$($parameter.Name) is specified" { -# Mock -CommandName Get-VM -MockWith { -# return @{ -# State = 'Running' -# } -# } - -# Set-TargetResource @setTargetResourceParams - -# Assert-MockCalled -CommandName Set-VMProcessor -Scope It -Exactly 1 -# Assert-MockCalled -CommandName Set-VMProperty -Scope It -Exactly 0 -# } -# } -# } # describe Set-TargetResource - -# Describe 'DSC_VMProcessor\Assert-TargetResourceParameter' { - -# # Return Windows Server 2012 R2/Windows 8.1 Update 1 -# Mock -CommandName Get-CimInstance { return @{ BuildNumber = '9600' } } - -# It "Should not throw when parameter 'ResourcePoolName' is specified on 2012 R2 host" { -# { Assert-TargetResourceParameter -ResourcePoolName 'TestPool' } | Should -Not -throw -# } - -# $server2016OnlyParameters = @{ -# EnableHostResourceProtection = $true -# ExposeVirtualizationExtensions = $true -# HwThreadCountPerCore = 1 -# } - -# foreach ($parameter in $server2016OnlyParameters.GetEnumerator()) -# { -# $assertTargetResourceParameterParams = @{ -# $parameter.Name = $parameter.Value -# } - -# It "Should throw when parameter '$($parameter.Name)' is specified on 2012 R2 host" { -# { Assert-TargetResourceParameter @assertTargetResourceParameterParams } | Should -Throw '14393' -# } -# } -# } # describe Assert-TargetResourceParameter -# } # InModuleScope -# } -# finally -# { -# Invoke-TestCleanup -# } + # Import the stub functions. + Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +} + +function Invoke-TestCleanup +{ + Restore-TestEnvironment -TestEnvironment $script:testEnvironment +} + +Invoke-TestSetup + +try +{ + InModuleScope $script:dscResourceName { + + $testVMName = 'UnitTestVM' + $testResourcePoolName = 'Unit Test Resource Pool' + + Describe 'DSC_VMProcessor\Get-TargetResource' { + + $fakeVMProcessor = @{ + EnableHostResourceProtection = $true + } + + # Guard mocks + Mock -CommandName Assert-Module + + It 'Should return a [System.Collections.Hashtable] object type' { + Mock -CommandName Get-VMProcessor { return $fakeVMProcessor } + + $result = Get-TargetResource -VMName $testVMName + + $result -is [System.Collections.Hashtable] | Should -Be $true + } + + It 'Should assert Hyper-V module is installed' { + Mock -CommandName Assert-Module + Mock -CommandName Get-VMProcessor { return $fakeVMProcessor } + + $null = Get-TargetResource -VMName $testVMName + + Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It + } + + It 'Should throw when VM processor is not found' { + Mock -CommandName Get-Module { return $true } + Mock -CommandName Get-VMProcessor { Write-Error 'Not Found' } + { $null = Get-TargetResource -VMName $testVMName } | Should -Throw 'Not Found' + } + } # descrive Get-TargetResource + + Describe 'DSC_VMProcessor\Test-TargetResource' { + + # Guard mocks + Mock -CommandName Assert-Module + Mock -CommandName Assert-TargetResourceParameter + + $fakeTargetResource = @{ + VMName = $testVMName + EnableHostResourceProtection = $true + ExposeVirtualizationExtensions = $true + HwThreadCountPerCore = 1 + Maximum = 99 + MaximumCountPerNumaNode = 4 + MaximumCountPerNumaSocket = 1 + RelativeWeight = 99 + Reserve = 0 + ResourcePoolName = $testResourcePoolName + CompatibilityForMigrationEnabled = $false + CompatibilityForOlderOperatingSystemsEnabled = $false + } + + It 'Should return a [System.Boolean] object type' { + Mock -CommandName Get-TargetResource { return $fakeTargetResource } + + $result = Test-TargetResource -VMName $testVMName + + $result -is [System.Boolean] | Should -Be $true + } + + It 'Should assert Hyper-V module is installed' { + Mock -CommandName Get-VMProcessor { return $fakeVMProcessor } + + $null = Test-TargetResource -VMName $testVMName + + Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It + } + + It 'Should assert parameter values are valid' { + Mock -CommandName Get-VMProcessor { return $fakeVMProcessor } + + $null = Test-TargetResource -VMName $testVMName + + Assert-MockCalled -CommandName Assert-TargetResourceParameter -Scope It + } + + $parameterNames = @( + 'EnableHostResourceProtection', + 'ExposeVirtualizationExtensions', + 'HwThreadCountPerCore', + 'Maximum', + 'MaximumCountPerNumaNode', + 'MaximumCountPerNumaSocket', + 'RelativeWeight', + 'Reserve', + 'ResourcePoolName', + 'CompatibilityForMigrationEnabled', + 'CompatibilityForOlderOperatingSystemsEnabled' + ) + + # Test each individual parameter value separately + foreach ($parameterName in $parameterNames) + { + $parameterValue = $fakeTargetResource[$parameterName] + $testTargetResourceParams = @{ + VMName = $testVMName + } + + # Pass value verbatim so it should always pass first + It "Should pass when parameter '$parameterName' is correct" { + $testTargetResourceParams[$parameterName] = $parameterValue + + $result = Test-TargetResource @testTargetResourceParams + + $result | Should -Be $true + } + + if ($parameterValue -is [System.Boolean]) + { + # Invert parameter value to cause a test failure + $testTargetResourceParams[$parameterName] = -not $parameterValue + } + elseif ($parameterValue -is [System.String]) + { + # Repeat string to cause a test failure + $testTargetResourceParams[$parameterName] = "$parameterValue$parameterValue" + } + elseif ($parameterValue -is [System.Int32] -or $parameterValue -is [System.Int64]) + { + # Add one to cause a test failure + $testTargetResourceParams[$parameterName] = $parameterValue + 1 + } + + It "Should fail when parameter '$parameterName' is incorrect" { + $result = Test-TargetResource @testTargetResourceParams + + $result | Should -Be $false + } + } + } # describe Test-TargetResource + + Describe 'DSC_VMProcessor\Set-TargetResource' { + # Guard mocks + Mock -CommandName Assert-Module + Mock -CommandName Assert-TargetResourceParameter + Mock -CommandName Get-VM + Mock -CommandName Set-VMProcessor + Mock -CommandName Set-VMProperty + + It 'Should assert Hyper-V module is installed' { + $null = Set-TargetResource -VMName $testVMName + + Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It + } + + It 'Should assert parameter values are valid' { + $null = Set-TargetResource -VMName $testVMName + + Assert-MockCalled -CommandName Assert-TargetResourceParameter -Scope It + } + + $restartRequiredParameters = @{ + 'ExposeVirtualizationExtensions' = $false + 'CompatibilityForMigrationEnabled' = $true + 'CompatibilityForOlderOperatingSystemsEnabled' = $true + 'HwThreadCountPerCore' = 2 + 'MaximumCountPerNumaNode' = 2 + 'MaximumCountPerNumaSocket' = 2 + 'ResourcePoolName' = $testResourcePoolName + } + + foreach ($parameter in $restartRequiredParameters.GetEnumerator()) + { + $setTargetResourceParams = @{ + VMName = $testVMName + $parameter.Name = $parameter.Value + } + + It "Should not throw when VM is off, '$($parameter.Name)' is specified and 'RestartIfNeeded' is False" { + Mock -CommandName Get-VM -MockWith { + return @{ + State = 'Off' + } + } + + { Set-TargetResource @setTargetResourceParams } | Should -Not -throw + } + + It "Should throw when VM is running, '$($parameter.Name)' is specified and 'RestartIfNeeded' is False" { + Mock -CommandName Get-VM { return @{ State = 'Running' } } + + { Set-TargetResource @setTargetResourceParams } | Should -Throw + } + + It "Should shutdown VM when running, '$($parameter.Name)' is specified and 'RestartIfNeeded' is True" { + Mock -CommandName Get-VM { return @{ State = 'Running' } } + + Set-TargetResource @setTargetResourceParams -RestartIfNeeded $true + + Assert-MockCalled -CommandName Set-VMProperty -Scope It -Exactly 1 + } + } + + $noRestartRequiredParameters = @{ + 'EnableHostResourceProtection' = $true + 'Maximum' = 50 + 'RelativeWeight' = 50 + 'Reserve' = 50 + } + + foreach ($parameter in $noRestartRequiredParameters.GetEnumerator()) + { + $setTargetResourceParams = @{ + VMName = $testVMName + $parameter.Name = $parameter.Value + } + + It "Should not shutdown VM running and '$($parameter.Name) is specified" { + Mock -CommandName Get-VM -MockWith { + return @{ + State = 'Running' + } + } + + Set-TargetResource @setTargetResourceParams + + Assert-MockCalled -CommandName Set-VMProcessor -Scope It -Exactly 1 + Assert-MockCalled -CommandName Set-VMProperty -Scope It -Exactly 0 + } + } + } # describe Set-TargetResource + + Describe 'DSC_VMProcessor\Assert-TargetResourceParameter' { + + # Return Windows Server 2012 R2/Windows 8.1 Update 1 + Mock -CommandName Get-CimInstance { return @{ BuildNumber = '9600' } } + + It "Should not throw when parameter 'ResourcePoolName' is specified on 2012 R2 host" { + { Assert-TargetResourceParameter -ResourcePoolName 'TestPool' } | Should -Not -throw + } + + $server2016OnlyParameters = @{ + EnableHostResourceProtection = $true + ExposeVirtualizationExtensions = $true + HwThreadCountPerCore = 1 + } + + foreach ($parameter in $server2016OnlyParameters.GetEnumerator()) + { + $assertTargetResourceParameterParams = @{ + $parameter.Name = $parameter.Value + } + + It "Should throw when parameter '$($parameter.Name)' is specified on 2012 R2 host" { + { Assert-TargetResourceParameter @assertTargetResourceParameterParams } | Should -Throw '14393' + } + } + } # describe Assert-TargetResourceParameter + } # InModuleScope +} +finally +{ + Invoke-TestCleanup +} diff --git a/tests/Unit/DSC_VMScsiController.Tests.ps1 b/tests/Unit/DSC_VMScsiController.Tests.ps1 index a917f2a..7b455b5 100644 --- a/tests/Unit/DSC_VMScsiController.Tests.ps1 +++ b/tests/Unit/DSC_VMScsiController.Tests.ps1 @@ -1,350 +1,350 @@ -# $script:dscModuleName = 'HyperVDsc' -# $script:dscResourceName = 'DSC_VMScsiController' +$script:dscModuleName = 'HyperVDsc' +$script:dscResourceName = 'DSC_VMScsiController' -# function Invoke-TestSetup -# { -# try -# { -# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' -# } -# catch [System.IO.FileNotFoundException] -# { -# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' -# } +function Invoke-TestSetup +{ + try + { + Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + } -# $script:testEnvironment = Initialize-TestEnvironment ` -# -DSCModuleName $script:dscModuleName ` -# -DSCResourceName $script:dscResourceName ` -# -ResourceType 'Mof' ` -# -TestType 'Unit' + $script:testEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:dscModuleName ` + -DSCResourceName $script:dscResourceName ` + -ResourceType 'Mof' ` + -TestType 'Unit' -# # Import the stub functions. -# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -# } + # Import the stub functions. + Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +} -# function Invoke-TestCleanup -# { -# Restore-TestEnvironment -TestEnvironment $script:testEnvironment -# } +function Invoke-TestCleanup +{ + Restore-TestEnvironment -TestEnvironment $script:testEnvironment +} -# Invoke-TestSetup +Invoke-TestSetup -# try -# { -# InModuleScope $script:dscResourceName { +try +{ + InModuleScope $script:dscResourceName { -# $testVMName = 'UnitTestVM' + $testVMName = 'UnitTestVM' -# Describe 'DSC_VMScsiController\Get-TargetResource' { + Describe 'DSC_VMScsiController\Get-TargetResource' { -# $stubScsiController = @{ -# VMName = $testVMName -# ControllerNumber = 0 -# } + $stubScsiController = @{ + VMName = $testVMName + ControllerNumber = 0 + } -# # Guard mocks -# Mock -CommandName Assert-Module + # Guard mocks + Mock -CommandName Assert-Module -# It 'Should return a [System.Collections.Hashtable] object type' { -# Mock -CommandName Get-VMScsiController { return $stubScsiController } + It 'Should return a [System.Collections.Hashtable] object type' { + Mock -CommandName Get-VMScsiController { return $stubScsiController } -# $result = Get-TargetResource -VMName $testVMName -ControllerNumber 0 + $result = Get-TargetResource -VMName $testVMName -ControllerNumber 0 -# $result -is [System.Collections.Hashtable] | Should -Be $true -# } + $result -is [System.Collections.Hashtable] | Should -Be $true + } -# It 'Should return "Present" when controller is attached' { -# Mock -CommandName Get-VMScsiController { return $stubScsiController } + It 'Should return "Present" when controller is attached' { + Mock -CommandName Get-VMScsiController { return $stubScsiController } -# $result = Get-TargetResource -VMName $testVMName -ControllerNumber 0 + $result = Get-TargetResource -VMName $testVMName -ControllerNumber 0 -# $result.Ensure | Should -Be 'Present' -# } + $result.Ensure | Should -Be 'Present' + } -# It 'Should return "Absent" when controller is not attached' { -# Mock -CommandName Get-VMScsiController + It 'Should return "Absent" when controller is not attached' { + Mock -CommandName Get-VMScsiController -# $result = Get-TargetResource -VMName $testVMName -ControllerNumber 0 - -# $result.Ensure | Should -Be 'Absent' -# } + $result = Get-TargetResource -VMName $testVMName -ControllerNumber 0 + + $result.Ensure | Should -Be 'Absent' + } -# It 'Should assert Hyper-V module is installed' { -# Mock -CommandName Assert-Module -# Mock -CommandName Get-VMScsiController + It 'Should assert Hyper-V module is installed' { + Mock -CommandName Assert-Module + Mock -CommandName Get-VMScsiController -# $null = Get-TargetResource -VMName $testVMName -ControllerNumber 0 - -# Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It -# } -# } # describe Get-TargetResource - -# Describe 'DSC_VMScsiController\Test-TargetResource' { + $null = Get-TargetResource -VMName $testVMName -ControllerNumber 0 + + Assert-MockCalled -CommandName Assert-Module -ParameterFilter { $ModuleName -eq 'Hyper-V' } -Scope It + } + } # describe Get-TargetResource + + Describe 'DSC_VMScsiController\Test-TargetResource' { -# # Guard mocks -# Mock -CommandName Assert-Module + # Guard mocks + Mock -CommandName Assert-Module -# $stubTargetResource = @{ -# VMName = $testVMName -# ControllerNumber = 0 -# Ensure = 'Present' -# } - -# It 'Should return a [System.Boolean] object type' { -# Mock -CommandName Get-TargetResource { return $stubTargetResource } -# $testTargetResourceParams = @{ -# VMName = $testVMName -# ControllerNumber = 0 -# } - -# $result = Test-TargetResource @testTargetResourceParams - -# $result -is [System.Boolean] | Should -Be $true -# } - -# It "Should pass when parameter 'Ensure' is correct" { -# Mock -CommandName Get-TargetResource { return $stubTargetResource } -# $testTargetResourceParams = @{ -# VMName = $testVMName -# ControllerNumber = 0 -# Ensure = $stubTargetResource['Ensure'] -# } + $stubTargetResource = @{ + VMName = $testVMName + ControllerNumber = 0 + Ensure = 'Present' + } + + It 'Should return a [System.Boolean] object type' { + Mock -CommandName Get-TargetResource { return $stubTargetResource } + $testTargetResourceParams = @{ + VMName = $testVMName + ControllerNumber = 0 + } + + $result = Test-TargetResource @testTargetResourceParams + + $result -is [System.Boolean] | Should -Be $true + } + + It "Should pass when parameter 'Ensure' is correct" { + Mock -CommandName Get-TargetResource { return $stubTargetResource } + $testTargetResourceParams = @{ + VMName = $testVMName + ControllerNumber = 0 + Ensure = $stubTargetResource['Ensure'] + } -# $result = Test-TargetResource @testTargetResourceParams + $result = Test-TargetResource @testTargetResourceParams -# $result | Should -Be $true -# } + $result | Should -Be $true + } -# It "Should fail when parameter 'Ensure' is incorrect" { -# Mock -CommandName Get-TargetResource { return $stubTargetResource } -# $testTargetResourceParams = @{ -# VMName = $testVMName -# ControllerNumber = 0 -# Ensure = 'Absent' -# } - -# $result = Test-TargetResource @testTargetResourceParams + It "Should fail when parameter 'Ensure' is incorrect" { + Mock -CommandName Get-TargetResource { return $stubTargetResource } + $testTargetResourceParams = @{ + VMName = $testVMName + ControllerNumber = 0 + Ensure = 'Absent' + } + + $result = Test-TargetResource @testTargetResourceParams -# $result | Should -Be $false -# } -# } # describe Test-TargetResource + $result | Should -Be $false + } + } # describe Test-TargetResource -# Describe 'DSC_VMScsiController\Set-TargetResource' { -# # Guard mocks -# Mock -CommandName Assert-Module -# Mock -CommandName Get-VMScsiController -# Mock -CommandName Add-VMScsiController -# Mock -CommandName Remove-VMScsiController -# Mock -CommandName Remove-VMHardDiskDrive -# Mock -CommandName Set-VMState - -# It 'Should assert Hyper-V module is installed' { -# Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } -# $setTargetResourceParams = @{ -# VMName = $testVMName -# ControllerNumber = 0 -# RestartIfNeeded = $true -# } - -# $null = Set-TargetResource @setTargetResourceParams - -# Assert-MockCalled -CommandName Assert-Module -# } - -# It 'Should throw if "RestartIfNeeded" is not specified and VM is "Running"' { -# Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } -# $setTargetResourceParams = @{ -# VMName = $testVMName -# ControllerNumber = 0 -# } - -# { Set-TargetResource @setTargetResourceParams } | Should -Throw 'RestartIfNeeded' -# } - -# It 'Should not throw if "RestartIfNeeded" is not specified and VM is "Off"' { -# Mock -CommandName Get-VMHyperV { return @{ State = 'Off' } } -# $setTargetResourceParams = @{ -# VMName = $testVMName -# ControllerNumber = 0 -# } - -# { Set-TargetResource @setTargetResourceParams } | Should -Not -throw -# } - -# It 'Should call "Set-VMState" to stop running VM' { -# Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } -# $setTargetResourceParams = @{ -# VMName = $testVMName -# ControllerNumber = 0 -# RestartIfNeeded = $true -# } - -# $null = Set-TargetResource @setTargetResourceParams - -# Assert-MockCalled -CommandName Set-VMState -ParameterFilter { $State -eq 'Off' } -Scope It -# } - -# It 'Should call "Set-VMState" to restore VM to its previous state' { -# $testVMState = 'Paused' -# Mock -CommandName Get-VMHyperV { return @{ State = $testVMState } } -# $setTargetResourceParams = @{ -# VMName = $testVMName -# ControllerNumber = 0 -# RestartIfNeeded = $true -# } - -# $null = Set-TargetResource @setTargetResourceParams - -# Assert-MockCalled -CommandName Set-VMState -ParameterFilter { $State -eq $testVMState } -Scope It -# } - -# It 'Should add single controller when it does not exist' { -# Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } -# Mock -CommandName Get-VMScsiController -# $setTargetResourceParams = @{ -# VMName = $testVMName -# ControllerNumber = 0 -# RestartIfNeeded = $true -# } - -# $null = Set-TargetResource @setTargetResourceParams - -# Assert-MockCalled -CommandName Add-VMScsiController -Scope It -Exactly 1 -# } - -# It 'Should add single controller when one already exists' { -# Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } -# $fakeVMScsiController = [PSCustomObject] @{ ControllerNumber = 0 } -# Mock -CommandName Get-VMScsiController { return $fakeVMScsiController } -# $setTargetResourceParams = @{ -# VMName = $testVMName -# ControllerNumber = 1 -# RestartIfNeeded = $true -# } - -# $null = Set-TargetResource @setTargetResourceParams - -# Assert-MockCalled -CommandName Add-VMScsiController -Scope It -Exactly 1 -# } - -# It 'Should throw when adding controller when intermediate controller(s) do not exist' { -# Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } -# Mock -CommandName Get-VMScsiController -# $setTargetResourceParams = @{ -# VMName = $testVMName -# ControllerNumber = 1 -# RestartIfNeeded = $true -# } - -# { Set-TargetResource @setTargetResourceParams } | Should -Throw 'Cannot add controller' -# } - -# It 'Should remove controller when Ensure = "Absent"' { -# Mock -CommandName Get-VMHyperV { -# return @{ -# State = 'Running' -# } -# } - -# $stubHardDiskDrive = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() -# $stubHardDiskDrive.CimSession = New-MockObject -Type CimSession -# $stubHardDiskDrive.Path = 'TestDrive:\disk1.vhdx' -# $stubHardDiskDrive.ControllerLocation = 0 -# $stubHardDiskDrive.ControllerNumber = 0 -# $stubHardDiskDrive.ControllerType = 'SCSI' - -# $mockVMScsiController = [Microsoft.HyperV.PowerShell.VMScsiController]::CreateTypeInstance() -# $mockVMScsiController.Drives = @( -# $stubHardDiskDrive -# ) - -# # Mock getting all the available controllers -# Mock -CommandName Get-VMScsiController -MockWith { -# return @( -# 'mockController1' -# 'mockController2' -# ) -# } - -# # Mock getting the specific controller with ControllerNumber -eq 1 -# Mock -CommandName Get-VMScsiController -MockWith { -# return $mockVMScsiController -# } -ParameterFilter { -# $ControllerNumber -eq 1 -# } - -# $setTargetResourceParams = @{ -# VMName = $testVMName -# ControllerNumber = 1 -# RestartIfNeeded = $true -# Ensure = 'Absent' -# } - -# $null = Set-TargetResource @setTargetResourceParams -WarningAction SilentlyContinue - -# Assert-MockCalled -CommandName Remove-VMScsiController -Scope It -# } - -# It 'Should remove all attached disks when Ensure = "Absent"' { -# Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } - -# $stubHardDiskDrive1 = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() -# $stubHardDiskDrive1.CimSession = New-MockObject -Type CimSession -# $stubHardDiskDrive1.Name = 'Hard Drive on SCSI controller number 0 at location 0' -# $stubHardDiskDrive1.Path = 'TestDrive:\disk1.vhdx' -# $stubHardDiskDrive1.ControllerLocation = 0 -# $stubHardDiskDrive1.ControllerNumber = 0 -# $stubHardDiskDrive1.ControllerType = 'SCSI' - -# $stubHardDiskDrive2 = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() -# $stubHardDiskDrive2.CimSession = New-MockObject -Type CimSession -# $stubHardDiskDrive2.Name = 'Hard Drive on SCSI controller number 0 at location 1' -# $stubHardDiskDrive2.Path = 'TestDrive:\disk2.vhdx' -# $stubHardDiskDrive2.ControllerLocation = 0 -# $stubHardDiskDrive2.ControllerNumber = 0 -# $stubHardDiskDrive2.ControllerType = 'SCSI' - -# $mockVMScsiController = [Microsoft.HyperV.PowerShell.VMScsiController]::CreateTypeInstance() -# $mockVMScsiController.Drives = @( -# $stubHardDiskDrive1 -# $stubHardDiskDrive2 -# ) - -# Mock -CommandName Get-VMScsiController { return $mockVMScsiController } - -# $setTargetResourceParams = @{ -# VMName = $testVMName -# ControllerNumber = 0 -# RestartIfNeeded = $true -# Ensure = 'Absent' -# } - -# $null = Set-TargetResource @setTargetResourceParams -WarningAction SilentlyContinue - -# Assert-MockCalled -CommandName Remove-VMHardDiskDrive -Scope It -Exactly ($mockVMScsiController.Drives.Count) -# } - -# It 'Should throw removing a controller when additional/subsequent controller(s) exist' { -# Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } -# $fakeVMScsiControllers = @( -# [PSCustomObject] @{ ControllerNumber = 0 } -# [PSCustomObject] @{ ControllerNumber = 1 } -# ) -# Mock -CommandName Get-VMScsiController { return $fakeVMScsiControllers } -# $setTargetResourceParams = @{ -# VMName = $testVMName -# ControllerNumber = 0 -# RestartIfNeeded = $true -# Ensure = 'Absent' -# } - -# { Set-TargetResource @setTargetResourceParams } | Should -Throw 'Cannot remove controller' -# } - -# } # describe Set-TargetResource -# } # InModuleScope -# } -# finally -# { -# Invoke-TestCleanup -# } + Describe 'DSC_VMScsiController\Set-TargetResource' { + # Guard mocks + Mock -CommandName Assert-Module + Mock -CommandName Get-VMScsiController + Mock -CommandName Add-VMScsiController + Mock -CommandName Remove-VMScsiController + Mock -CommandName Remove-VMHardDiskDrive + Mock -CommandName Set-VMState + + It 'Should assert Hyper-V module is installed' { + Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } + $setTargetResourceParams = @{ + VMName = $testVMName + ControllerNumber = 0 + RestartIfNeeded = $true + } + + $null = Set-TargetResource @setTargetResourceParams + + Assert-MockCalled -CommandName Assert-Module + } + + It 'Should throw if "RestartIfNeeded" is not specified and VM is "Running"' { + Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } + $setTargetResourceParams = @{ + VMName = $testVMName + ControllerNumber = 0 + } + + { Set-TargetResource @setTargetResourceParams } | Should -Throw 'RestartIfNeeded' + } + + It 'Should not throw if "RestartIfNeeded" is not specified and VM is "Off"' { + Mock -CommandName Get-VMHyperV { return @{ State = 'Off' } } + $setTargetResourceParams = @{ + VMName = $testVMName + ControllerNumber = 0 + } + + { Set-TargetResource @setTargetResourceParams } | Should -Not -throw + } + + It 'Should call "Set-VMState" to stop running VM' { + Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } + $setTargetResourceParams = @{ + VMName = $testVMName + ControllerNumber = 0 + RestartIfNeeded = $true + } + + $null = Set-TargetResource @setTargetResourceParams + + Assert-MockCalled -CommandName Set-VMState -ParameterFilter { $State -eq 'Off' } -Scope It + } + + It 'Should call "Set-VMState" to restore VM to its previous state' { + $testVMState = 'Paused' + Mock -CommandName Get-VMHyperV { return @{ State = $testVMState } } + $setTargetResourceParams = @{ + VMName = $testVMName + ControllerNumber = 0 + RestartIfNeeded = $true + } + + $null = Set-TargetResource @setTargetResourceParams + + Assert-MockCalled -CommandName Set-VMState -ParameterFilter { $State -eq $testVMState } -Scope It + } + + It 'Should add single controller when it does not exist' { + Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } + Mock -CommandName Get-VMScsiController + $setTargetResourceParams = @{ + VMName = $testVMName + ControllerNumber = 0 + RestartIfNeeded = $true + } + + $null = Set-TargetResource @setTargetResourceParams + + Assert-MockCalled -CommandName Add-VMScsiController -Scope It -Exactly 1 + } + + It 'Should add single controller when one already exists' { + Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } + $fakeVMScsiController = [PSCustomObject] @{ ControllerNumber = 0 } + Mock -CommandName Get-VMScsiController { return $fakeVMScsiController } + $setTargetResourceParams = @{ + VMName = $testVMName + ControllerNumber = 1 + RestartIfNeeded = $true + } + + $null = Set-TargetResource @setTargetResourceParams + + Assert-MockCalled -CommandName Add-VMScsiController -Scope It -Exactly 1 + } + + It 'Should throw when adding controller when intermediate controller(s) do not exist' { + Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } + Mock -CommandName Get-VMScsiController + $setTargetResourceParams = @{ + VMName = $testVMName + ControllerNumber = 1 + RestartIfNeeded = $true + } + + { Set-TargetResource @setTargetResourceParams } | Should -Throw 'Cannot add controller' + } + + It 'Should remove controller when Ensure = "Absent"' { + Mock -CommandName Get-VMHyperV { + return @{ + State = 'Running' + } + } + + $stubHardDiskDrive = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() + $stubHardDiskDrive.CimSession = New-MockObject -Type CimSession + $stubHardDiskDrive.Path = 'TestDrive:\disk1.vhdx' + $stubHardDiskDrive.ControllerLocation = 0 + $stubHardDiskDrive.ControllerNumber = 0 + $stubHardDiskDrive.ControllerType = 'SCSI' + + $mockVMScsiController = [Microsoft.HyperV.PowerShell.VMScsiController]::CreateTypeInstance() + $mockVMScsiController.Drives = @( + $stubHardDiskDrive + ) + + # Mock getting all the available controllers + Mock -CommandName Get-VMScsiController -MockWith { + return @( + 'mockController1' + 'mockController2' + ) + } + + # Mock getting the specific controller with ControllerNumber -eq 1 + Mock -CommandName Get-VMScsiController -MockWith { + return $mockVMScsiController + } -ParameterFilter { + $ControllerNumber -eq 1 + } + + $setTargetResourceParams = @{ + VMName = $testVMName + ControllerNumber = 1 + RestartIfNeeded = $true + Ensure = 'Absent' + } + + $null = Set-TargetResource @setTargetResourceParams -WarningAction SilentlyContinue + + Assert-MockCalled -CommandName Remove-VMScsiController -Scope It + } + + It 'Should remove all attached disks when Ensure = "Absent"' { + Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } + + $stubHardDiskDrive1 = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() + $stubHardDiskDrive1.CimSession = New-MockObject -Type CimSession + $stubHardDiskDrive1.Name = 'Hard Drive on SCSI controller number 0 at location 0' + $stubHardDiskDrive1.Path = 'TestDrive:\disk1.vhdx' + $stubHardDiskDrive1.ControllerLocation = 0 + $stubHardDiskDrive1.ControllerNumber = 0 + $stubHardDiskDrive1.ControllerType = 'SCSI' + + $stubHardDiskDrive2 = [Microsoft.HyperV.PowerShell.HardDiskDrive]::CreateTypeInstance() + $stubHardDiskDrive2.CimSession = New-MockObject -Type CimSession + $stubHardDiskDrive2.Name = 'Hard Drive on SCSI controller number 0 at location 1' + $stubHardDiskDrive2.Path = 'TestDrive:\disk2.vhdx' + $stubHardDiskDrive2.ControllerLocation = 0 + $stubHardDiskDrive2.ControllerNumber = 0 + $stubHardDiskDrive2.ControllerType = 'SCSI' + + $mockVMScsiController = [Microsoft.HyperV.PowerShell.VMScsiController]::CreateTypeInstance() + $mockVMScsiController.Drives = @( + $stubHardDiskDrive1 + $stubHardDiskDrive2 + ) + + Mock -CommandName Get-VMScsiController { return $mockVMScsiController } + + $setTargetResourceParams = @{ + VMName = $testVMName + ControllerNumber = 0 + RestartIfNeeded = $true + Ensure = 'Absent' + } + + $null = Set-TargetResource @setTargetResourceParams -WarningAction SilentlyContinue + + Assert-MockCalled -CommandName Remove-VMHardDiskDrive -Scope It -Exactly ($mockVMScsiController.Drives.Count) + } + + It 'Should throw removing a controller when additional/subsequent controller(s) exist' { + Mock -CommandName Get-VMHyperV { return @{ State = 'Running' } } + $fakeVMScsiControllers = @( + [PSCustomObject] @{ ControllerNumber = 0 } + [PSCustomObject] @{ ControllerNumber = 1 } + ) + Mock -CommandName Get-VMScsiController { return $fakeVMScsiControllers } + $setTargetResourceParams = @{ + VMName = $testVMName + ControllerNumber = 0 + RestartIfNeeded = $true + Ensure = 'Absent' + } + + { Set-TargetResource @setTargetResourceParams } | Should -Throw 'Cannot remove controller' + } + + } # describe Set-TargetResource + } # InModuleScope +} +finally +{ + Invoke-TestCleanup +} diff --git a/tests/Unit/DSC_VMSwitch_BandwidthReservationMode.Tests.ps1 b/tests/Unit/DSC_VMSwitch_BandwidthReservationMode.Tests.ps1 index 55a0aa5..95aee4a 100644 --- a/tests/Unit/DSC_VMSwitch_BandwidthReservationMode.Tests.ps1 +++ b/tests/Unit/DSC_VMSwitch_BandwidthReservationMode.Tests.ps1 @@ -1,479 +1,479 @@ -# $script:dscModuleName = 'HyperVDsc' -# $script:dscResourceName = 'DSC_VMSwitch' - -# function Invoke-TestSetup -# { -# try -# { -# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' -# } -# catch [System.IO.FileNotFoundException] -# { -# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' -# } - -# $script:testEnvironment = Initialize-TestEnvironment ` -# -DSCModuleName $script:dscModuleName ` -# -DSCResourceName $script:dscResourceName ` -# -ResourceType 'Mof' ` -# -TestType 'Unit' - -# # Import the stub functions. -# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -# } - -# function Invoke-TestCleanup -# { -# Restore-TestEnvironment -TestEnvironment $script:testEnvironment -# } - -# Invoke-TestSetup - -# try -# { -# InModuleScope $script:dscResourceName { - -# <# -# 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)] -# [System.String] -# $Name, - -# [Parameter(Mandatory = $true)] -# [ValidateSet('Default', 'Weight', 'Absolute', 'None', 'NA')] -# [System.String] -# $BandwidthReservationMode, - -# [Parameter()] -# [System.Boolean] -# $AllowManagementOS = $false -# ) - -# $mockedVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() -# $mockedVMSwitch.Name = $Name -# $mockedVMSwitch.SwitchType = 'External' -# $mockedVMSwitch.AllowManagementOS = $AllowManagementOS -# $mockedVMSwitch.NetAdapterInterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver' - -# if ($BandwidthReservationMode -ne 'NA') -# { -# $mockedVMSwitch.BandwidthReservationMode = $BandwidthReservationMode -# } - -# return $mockedVMSwitch -# } - -# Describe 'Validates Get-TargetResource Function' { -# <# -# Mocks Get-VMSwitch and will return $script:mockedVMSwitch which is -# a variable that is created during most It statements to mock a VMSwitch -# #> -# Mock -CommandName Get-VMSwitch -MockWith { -# param -# ( -# [System.String] -# $ErrorAction -# ) - -# if ($ErrorAction -eq 'Stop' -and $script:mockedVMSwitch -eq $null) -# { -# throw [System.Management.Automation.ActionPreferenceStopException]'No switch can be found by given criteria.' -# } - -# return $script:mockedVMSwitch -# } - -# # 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 -# } - -# # Create all the test cases for Get-TargetResource -# $getTestCases = @() -# foreach ($brmMode in $BANDWIDTH_RESERVATION_MODES) { -# $getTestCases += @{ -# CurrentName = $brmMode + 'BRM' -# CurrentBandwidthReservationMode = $brmMode -# } -# } - -# # Test Get-TargetResource with the test cases created above -# It 'Current switch''s BandwidthReservationMode is set to ' -TestCases $getTestCases { -# param -# ( -# [Parameter()] -# [System.String] -# $CurrentName, - -# [Parameter()] -# [System.String] -# $CurrentBandwidthReservationMode -# ) - -# # Set the mocked VMSwitch to be returned from Get-VMSwitch based on the input from $getTestCases -# $script: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 'script' -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 -# $script: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 "Default" - -# Remove-Variable -Scope 'script' -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 -# } -# } - -# Describe 'Validates Test-TargetResource Function' { -# <# -# Mocks Get-VMSwitch and will return $script:mockedVMSwitch which is -# a variable that is created during most It statements to mock a VMSwitch -# #> -# Mock -CommandName Get-VMSwitch -MockWith { -# param ( -# [System.String] -# $ErrorAction -# ) - -# if ($ErrorAction -eq 'Stop' -and $script:mockedVMSwitch -eq $null) -# { -# throw [System.Management.Automation.ActionPreferenceStopException]'No switch can be found by given criteria.' -# } - -# return $script:mockedVMSwitch -# } - -# # 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 -CommandName Get-OSVersion -MockWith { -# return [Version]::Parse('6.3.9600') -# } - -# # Create all the test cases for Get-TargetResource -# $getTestCases = @() -# foreach ($brmMode in $BANDWIDTH_RESERVATION_MODES) -# { -# $getTestCases += @{ -# CurrentName = $brmMode + 'BRM' -# CurrentBandwidthReservationMode = $brmMode -# } -# } - -# # Test Test-TargetResource with the test cases created above -# It 'Current Name "" | Current BandwidthReservationMode set to "" | Desired BandwidthReservationMode set to "" | Ensure ""' -TestCases $testSetTestCases { -# param -# ( -# [Parameter()] -# [System.String] -# $CurrentName, - -# [Parameter()] -# [System.String] -# $CurrentBandwidthReservationMode, - -# [Parameter()] -# [System.String] -# $DesiredName, - -# [Parameter()] -# [System.String] -# $DesiredBandwidthReservationMode, - -# [Parameter()] -# [System.String] -# $Ensure, - -# [Parameter()] -# [System.Boolean] -# $ExpectedResult -# ) - -# # Set the mocked VMSwitch to be returned from Get-VMSwitch if the switch exists -# if ($CurrentName) -# { -# $script: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 'script' -Name 'mockedVMSwitch' -ErrorAction 'SilentlyContinue' -# } - -# Mock -CommandName Get-OSVersion -MockWith { -# return [Version]::Parse('6.1.7601') -# } - -# # Test Test-TargetResource when the version of Windows doesn't support BandwidthReservationMode -# It 'Invalid Operating System Exception' { -# $errorMessage = $script:localizedData.BandwidthReservationModeError - -# {Test-TargetResource -Name 'WeightBRM' -Type 'External' -NetAdapterName 'SomeNIC' -AllowManagementOS $true -BandwidthReservationMode 'Weight' -Ensure 'Present'} | Should -Throw $errorMessage -# } - -# It 'Passes when "BandwidthReservationMode" does not match but is not specified (#48)' { -# $script:mockedVMSwitch = New-MockedVMSwitch -Name 'SomeSwitch' -BandwidthReservationMode 'Absolute' -# $targetResource = Test-TargetResource -Name 'SomeSwitch' -Type 'Internal' -Ensure 'Present' -# $targetResource | Should -Be $true -# } -# } - -# Describe 'Validates Set-TargetResource Function' { -# <# -# Mocks Get-VMSwitch and will return $script:mockedVMSwitch which is -# a variable that is created during most It statements to mock a VMSwitch -# #> -# Mock -CommandName Get-VMSwitch -MockWith { -# param -# ( -# [System.String] -# $Name, - -# [System.String] -# $SwitchType, - -# [System.String] -# $ErrorAction -# ) - -# if ($ErrorAction -eq 'Stop' -and $script:mockedVMSwitch -eq $null) -# { -# throw [System.Management.Automation.ActionPreferenceStopException]'No switch can be found by given criteria.' -# } - -# return $script:mockedVMSwitch -# } - -# <# -# Mocks New-VMSwitch and will assign a mocked switch to $script:mockedVMSwitch. This returns $script:mockedVMSwitch -# which is a variable that is created during most It statements to mock a VMSwitch -# #> -# Mock -CommandName New-VMSwitch -MockWith { -# param -# ( -# [System.String] -# $Name, - -# [System.String] -# $NetAdapterName, - -# [System.String] -# $MinimumBandwidthMode, - -# [System.Boolean] -# $AllowManagementOS -# ) - -# $script:mockedVMSwitch = New-MockedVMSwitch -Name $Name -BandwidthReservationMode $MinimumBandwidthMode -AllowManagementOS $AllowManagementOS -# return $script:mockedVMSwitch -# } - -# <# -# Mocks Set-VMSwitch and will modify $script:mockedVMSwitch which is -# a variable that is created during most It statements to mock a VMSwitch -# #> -# Mock -CommandName Set-VMSwitch -MockWith { -# param -# ( -# [System.Boolean] -# $AllowManagementOS -# ) - -# if ($AllowManagementOS) -# { -# $script:mockedVMSwitch['AllowManagementOS'] = $AllowManagementOS -# } -# } - -# <# -# Mocks Remove-VMSwitch and will remove the variable $script:mockedVMSwitch which is -# a variable that is created during most It statements to mock a VMSwitch -# #> -# Mock -CommandName Remove-VMSwitch -MockWith { -# $script: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 -CommandName Get-OSVersion -MockWith { -# return [Version]::Parse('6.3.9600') -# } - -# It 'Current Name "" | Current BandwidthReservationMode set to "" | Desired BandwidthReservationMode set to "" | Ensure ""' -TestCases $testSetTestCases { -# param -# ( -# [Parameter()] -# [System.String] -# $CurrentName, - -# [Parameter()] -# [System.String] -# $CurrentBandwidthReservationMode, - -# [Parameter()] -# [System.String] -# $DesiredName, - -# [Parameter()] -# [System.String] -# $DesiredBandwidthReservationMode, - -# [Parameter()] -# [System.String] -# $Ensure, - -# [Parameter()] -# [System.Boolean] -# $ExpectedResult -# ) - -# if ($CurrentName) -# { -# # Set the mocked VMSwitch to be returned from Get-VMSwitch if the switch exists -# $script:mockedVMSwitch = New-MockedVMSwitch -Name $CurrentName -BandwidthReservationMode $CurrentBandwidthReservationMode -AllowManagementOS $true -# } -# else -# { -# if ($Ensure -eq 'Absent') -# { -# # This is called when Ensure = 'Absent'. TO make sure there is a VMSwitch to remove. -# $script:mockedVMSwitch = New-MockedVMSwitch -Name $DesiredName -BandwidthReservationMode $DesiredBandwidthReservationMode -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 'script' -Name 'mockedVMSwitch' -ErrorAction 'SilentlyContinue' -# } - -# # Test Set-TargetResource when the version of Windows doesn't support BandwidthReservationMode -# It 'Invalid Operating System Exception' { -# Mock -CommandName Get-OSVersion -MockWith { -# return [Version]::Parse('6.1.7601') -# } - -# $errorMessage = $script:localizedData.BandwidthReservationModeError - -# {Set-TargetResource -Name 'WeightBRM' -Type 'External' -NetAdapterName 'SomeNIC' -AllowManagementOS $true -BandwidthReservationMode 'Weight' -Ensure 'Present'} | Should -Throw $errorMessage -# } -# } -# } -# } -# finally -# { -# Invoke-TestCleanup -# } +$script:dscModuleName = 'HyperVDsc' +$script:dscResourceName = 'DSC_VMSwitch' + +function Invoke-TestSetup +{ + try + { + Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + } + + $script:testEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:dscModuleName ` + -DSCResourceName $script:dscResourceName ` + -ResourceType 'Mof' ` + -TestType 'Unit' + + # Import the stub functions. + Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +} + +function Invoke-TestCleanup +{ + Restore-TestEnvironment -TestEnvironment $script:testEnvironment +} + +Invoke-TestSetup + +try +{ + InModuleScope $script:dscResourceName { + + <# + 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)] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [ValidateSet('Default', 'Weight', 'Absolute', 'None', 'NA')] + [System.String] + $BandwidthReservationMode, + + [Parameter()] + [System.Boolean] + $AllowManagementOS = $false + ) + + $mockedVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() + $mockedVMSwitch.Name = $Name + $mockedVMSwitch.SwitchType = 'External' + $mockedVMSwitch.AllowManagementOS = $AllowManagementOS + $mockedVMSwitch.NetAdapterInterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver' + + if ($BandwidthReservationMode -ne 'NA') + { + $mockedVMSwitch.BandwidthReservationMode = $BandwidthReservationMode + } + + return $mockedVMSwitch + } + + Describe 'Validates Get-TargetResource Function' { + <# + Mocks Get-VMSwitch and will return $script:mockedVMSwitch which is + a variable that is created during most It statements to mock a VMSwitch + #> + Mock -CommandName Get-VMSwitch -MockWith { + param + ( + [System.String] + $ErrorAction + ) + + if ($ErrorAction -eq 'Stop' -and $script:mockedVMSwitch -eq $null) + { + throw [System.Management.Automation.ActionPreferenceStopException]'No switch can be found by given criteria.' + } + + return $script:mockedVMSwitch + } + + # 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 + } + + # Create all the test cases for Get-TargetResource + $getTestCases = @() + foreach ($brmMode in $BANDWIDTH_RESERVATION_MODES) { + $getTestCases += @{ + CurrentName = $brmMode + 'BRM' + CurrentBandwidthReservationMode = $brmMode + } + } + + # Test Get-TargetResource with the test cases created above + It 'Current switch''s BandwidthReservationMode is set to ' -TestCases $getTestCases { + param + ( + [Parameter()] + [System.String] + $CurrentName, + + [Parameter()] + [System.String] + $CurrentBandwidthReservationMode + ) + + # Set the mocked VMSwitch to be returned from Get-VMSwitch based on the input from $getTestCases + $script: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 'script' -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 + $script: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 "Default" + + Remove-Variable -Scope 'script' -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 + } + } + + Describe 'Validates Test-TargetResource Function' { + <# + Mocks Get-VMSwitch and will return $script:mockedVMSwitch which is + a variable that is created during most It statements to mock a VMSwitch + #> + Mock -CommandName Get-VMSwitch -MockWith { + param ( + [System.String] + $ErrorAction + ) + + if ($ErrorAction -eq 'Stop' -and $script:mockedVMSwitch -eq $null) + { + throw [System.Management.Automation.ActionPreferenceStopException]'No switch can be found by given criteria.' + } + + return $script:mockedVMSwitch + } + + # 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 -CommandName Get-OSVersion -MockWith { + return [Version]::Parse('6.3.9600') + } + + # Create all the test cases for Get-TargetResource + $getTestCases = @() + foreach ($brmMode in $BANDWIDTH_RESERVATION_MODES) + { + $getTestCases += @{ + CurrentName = $brmMode + 'BRM' + CurrentBandwidthReservationMode = $brmMode + } + } + + # Test Test-TargetResource with the test cases created above + It 'Current Name "" | Current BandwidthReservationMode set to "" | Desired BandwidthReservationMode set to "" | Ensure ""' -TestCases $testSetTestCases { + param + ( + [Parameter()] + [System.String] + $CurrentName, + + [Parameter()] + [System.String] + $CurrentBandwidthReservationMode, + + [Parameter()] + [System.String] + $DesiredName, + + [Parameter()] + [System.String] + $DesiredBandwidthReservationMode, + + [Parameter()] + [System.String] + $Ensure, + + [Parameter()] + [System.Boolean] + $ExpectedResult + ) + + # Set the mocked VMSwitch to be returned from Get-VMSwitch if the switch exists + if ($CurrentName) + { + $script: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 'script' -Name 'mockedVMSwitch' -ErrorAction 'SilentlyContinue' + } + + Mock -CommandName Get-OSVersion -MockWith { + return [Version]::Parse('6.1.7601') + } + + # Test Test-TargetResource when the version of Windows doesn't support BandwidthReservationMode + It 'Invalid Operating System Exception' { + $errorMessage = $script:localizedData.BandwidthReservationModeError + + {Test-TargetResource -Name 'WeightBRM' -Type 'External' -NetAdapterName 'SomeNIC' -AllowManagementOS $true -BandwidthReservationMode 'Weight' -Ensure 'Present'} | Should -Throw $errorMessage + } + + It 'Passes when "BandwidthReservationMode" does not match but is not specified (#48)' { + $script:mockedVMSwitch = New-MockedVMSwitch -Name 'SomeSwitch' -BandwidthReservationMode 'Absolute' + $targetResource = Test-TargetResource -Name 'SomeSwitch' -Type 'Internal' -Ensure 'Present' + $targetResource | Should -Be $true + } + } + + Describe 'Validates Set-TargetResource Function' { + <# + Mocks Get-VMSwitch and will return $script:mockedVMSwitch which is + a variable that is created during most It statements to mock a VMSwitch + #> + Mock -CommandName Get-VMSwitch -MockWith { + param + ( + [System.String] + $Name, + + [System.String] + $SwitchType, + + [System.String] + $ErrorAction + ) + + if ($ErrorAction -eq 'Stop' -and $script:mockedVMSwitch -eq $null) + { + throw [System.Management.Automation.ActionPreferenceStopException]'No switch can be found by given criteria.' + } + + return $script:mockedVMSwitch + } + + <# + Mocks New-VMSwitch and will assign a mocked switch to $script:mockedVMSwitch. This returns $script:mockedVMSwitch + which is a variable that is created during most It statements to mock a VMSwitch + #> + Mock -CommandName New-VMSwitch -MockWith { + param + ( + [System.String] + $Name, + + [System.String] + $NetAdapterName, + + [System.String] + $MinimumBandwidthMode, + + [System.Boolean] + $AllowManagementOS + ) + + $script:mockedVMSwitch = New-MockedVMSwitch -Name $Name -BandwidthReservationMode $MinimumBandwidthMode -AllowManagementOS $AllowManagementOS + return $script:mockedVMSwitch + } + + <# + Mocks Set-VMSwitch and will modify $script:mockedVMSwitch which is + a variable that is created during most It statements to mock a VMSwitch + #> + Mock -CommandName Set-VMSwitch -MockWith { + param + ( + [System.Boolean] + $AllowManagementOS + ) + + if ($AllowManagementOS) + { + $script:mockedVMSwitch['AllowManagementOS'] = $AllowManagementOS + } + } + + <# + Mocks Remove-VMSwitch and will remove the variable $script:mockedVMSwitch which is + a variable that is created during most It statements to mock a VMSwitch + #> + Mock -CommandName Remove-VMSwitch -MockWith { + $script: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 -CommandName Get-OSVersion -MockWith { + return [Version]::Parse('6.3.9600') + } + + It 'Current Name "" | Current BandwidthReservationMode set to "" | Desired BandwidthReservationMode set to "" | Ensure ""' -TestCases $testSetTestCases { + param + ( + [Parameter()] + [System.String] + $CurrentName, + + [Parameter()] + [System.String] + $CurrentBandwidthReservationMode, + + [Parameter()] + [System.String] + $DesiredName, + + [Parameter()] + [System.String] + $DesiredBandwidthReservationMode, + + [Parameter()] + [System.String] + $Ensure, + + [Parameter()] + [System.Boolean] + $ExpectedResult + ) + + if ($CurrentName) + { + # Set the mocked VMSwitch to be returned from Get-VMSwitch if the switch exists + $script:mockedVMSwitch = New-MockedVMSwitch -Name $CurrentName -BandwidthReservationMode $CurrentBandwidthReservationMode -AllowManagementOS $true + } + else + { + if ($Ensure -eq 'Absent') + { + # This is called when Ensure = 'Absent'. TO make sure there is a VMSwitch to remove. + $script:mockedVMSwitch = New-MockedVMSwitch -Name $DesiredName -BandwidthReservationMode $DesiredBandwidthReservationMode -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 'script' -Name 'mockedVMSwitch' -ErrorAction 'SilentlyContinue' + } + + # Test Set-TargetResource when the version of Windows doesn't support BandwidthReservationMode + It 'Invalid Operating System Exception' { + Mock -CommandName Get-OSVersion -MockWith { + return [Version]::Parse('6.1.7601') + } + + $errorMessage = $script:localizedData.BandwidthReservationModeError + + {Set-TargetResource -Name 'WeightBRM' -Type 'External' -NetAdapterName 'SomeNIC' -AllowManagementOS $true -BandwidthReservationMode 'Weight' -Ensure 'Present'} | Should -Throw $errorMessage + } + } + } +} +finally +{ + Invoke-TestCleanup +} diff --git a/tests/Unit/DSC_VMSwitch_EnableEmbeddedTeaming.Tests.ps1 b/tests/Unit/DSC_VMSwitch_EnableEmbeddedTeaming.Tests.ps1 index c450da2..c691353 100644 --- a/tests/Unit/DSC_VMSwitch_EnableEmbeddedTeaming.Tests.ps1 +++ b/tests/Unit/DSC_VMSwitch_EnableEmbeddedTeaming.Tests.ps1 @@ -1,494 +1,494 @@ -# $script:dscModuleName = 'HyperVDsc' -# $script:dscResourceName = 'DSC_VMSwitch' - -# function Invoke-TestSetup -# { -# try -# { -# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' -# } -# catch [System.IO.FileNotFoundException] -# { -# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' -# } - -# $script:testEnvironment = Initialize-TestEnvironment ` -# -DSCModuleName $script:dscModuleName ` -# -DSCResourceName $script:dscResourceName ` -# -ResourceType 'Mof' ` -# -TestType 'Unit' - -# # Import the stub functions. -# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -# } - -# function Invoke-TestCleanup -# { -# Restore-TestEnvironment -TestEnvironment $script:testEnvironment -# } - -# Invoke-TestSetup - -# try -# { -# InModuleScope $script:dscResourceName { -# # A helper function to mock a VMSwitch -# function New-MockedVMSwitch -# { -# param -# ( -# [Parameter(Mandatory = $true)] -# [System.String] -# $Name, - -# [Parameter(Mandatory = $true)] -# [ValidateSet('Default', 'Weight', 'Absolute', 'None', 'NA')] -# [System.String] -# $BandwidthReservationMode, - -# [Parameter()] -# [ValidateSet('Dynamic','HyperVPort')] -# [System.String] -# $LoadBalancingAlgorithm, - -# [Parameter()] -# [System.Boolean] -# $AllowManagementOS = $false -# ) - -# $mockedVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() -# $mockedVMSwitch.Name = $Name -# $mockedVMSwitch.SwitchType = 'External' -# $mockedVMSwitch.AllowManagementOS = $AllowManagementOS -# $mockedVMSwitch.NetAdapterInterfaceDescriptions = 'Microsoft Network Adapter Multiplexor Driver' - -# if ($BandwidthReservationMode -ne 'NA') -# { -# $mockedVMSwitch.BandwidthReservationMode = $BandwidthReservationMode -# } - -# if ($PSBoundParameters.ContainsKey('LoadBalancingAlgorithm')) -# { -# $mockedVMSwitch.LoadBalancingAlgorithm = $LoadBalancingAlgorithm -# } - -# return $mockedVMSwitch -# } - -# Describe "DSC_VMSwitch" { -# <# -# Mocks Get-VMSwitch and will return $script:mockedVMSwitch which is -# a variable that is created during most It statements to mock a VMSwitch -# #> -# Mock -CommandName Get-VMSwitch -MockWith { -# if ($ErrorAction -eq 'Stop' -and $script:mockedVMSwitch -eq $null) -# { -# throw [System.Management.Automation.ActionPreferenceStopException]'No switch can be found by given criteria.' -# } - -# return $script:mockedVMSwitch -# } - -# <# -# Mocks New-VMSwitch and will assign a mocked switch to $script:mockedVMSwitch. This returns $script:mockedVMSwitch -# which is a variable that is created during most It statements to mock a VMSwitch -# #> -# Mock -CommandName New-VMSwitch -MockWith { -# param -# ( -# [Parameter()] -# [System.String] -# $Name, - -# [Parameter()] -# [System.String[]] -# $NetAdapterName, - -# [Parameter()] -# [System.String] -# $MinimumBandwidthMode = 'NA', - -# [Parameter()] -# [System.Boolean] -# $EnableEmbeddedTeaming, - -# [Parameter()] -# [System.Boolean] -# $AllowManagementOS -# ) - -# $script:mockedVMSwitch = New-MockedVMSwitch -Name $Name -BandwidthReservationMode $MinimumBandwidthMode -AllowManagementOS $AllowManagementOS -# #is SET is enabled mok a VMSwitchTeam -# if ($EnableEmbeddedTeaming) -# { -# $script:mockedVMSwitchTeam = [PSCustomObject]@{ -# Name = "TestSwitch" -# Id = [Guid]::NewGuid() -# TeamingMode = 'SwitchIndependent' -# LoadBalancingAlgorithm = 'Dynamic' -# } -# } -# return $script:mockedVMSwitch -# } - -# Mock -CommandName Get-OSVersion -MockWith { -# return @{ -# Major = 10 -# } -# } - -# <# -# Mocks Remove-VMSwitch and will remove the variable $script:mockedVMSwitch which is -# a variable that is created during most It statements to mock a VMSwitch -# #> -# Mock -CommandName Remove-VMSwitch -MockWith { -# $script:mockedVMSwitch = $null -# } - -# <# -# Mocks Get-VMSwitchTeam and will return a moked VMSwitchTeam -# #> -# Mock -CommandName Get-VMSwitchTeam -MockWith { -# return $script:mockedVMSwitchTeam -# } - -# Mock -CommandName Set-VMSwitchTeam - -# # Mocks Get-NetAdapter which returns a simplified network adapter -# Mock -CommandName Get-NetAdapter -MockWith { -# return @( -# [PSCustomObject]@{ -# Name = 'NIC1' -# InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #1' -# } -# [PSCustomObject]@{ -# Name = 'NIC2' -# InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #2' -# } -# ) -# } - -# # 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 -# } - -# Context "A virtual switch with embedded teaming does not exist but should" { -# $script:mockedVMSwitch = $null - -# $testParams = @{ -# Name = "TestSwitch" -# Type = "External" -# NetAdapterName = @("NIC1", "NIC2") -# AllowManagementOS = $true -# EnableEmbeddedTeaming = $true -# BandwidthReservationMode = "NA" -# Ensure = "Present" -# } - -# It "Should return absent in the get method" { -# (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Absent" -# } - -# It "Should return false in the test method" { -# Test-TargetResource @testParams | Should -Be $false -# } - -# It "Should run the set method without exceptions" { -# Set-TargetResource @testParams -# Assert-MockCalled -CommandName "New-VMSwitch" -Times 1 -# } -# } - -# Context "A virtual switch with embedded teaming exists and should" { -# $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() -# $mockVMSwitch.Name = 'NewSwitch' -# $mockVMSwitch.SwitchType = 'External' -# $mockVMSwitch.AllowManagementOS = $true -# $mockVMSwitch.EmbeddedTeamingEnabled = $true -# $mockVMSwitch.Id = [Guid]::NewGuid() -# $mockVMSwitch.NetAdapterInterfaceDescriptions = @( -# 'Microsoft Network Adapter Multiplexor Driver #1', -# 'Microsoft Network Adapter Multiplexor Driver #2' -# ) - -# Mock -CommandName Get-VMSwitch -MockWith { -# return $mockVMSwitch -# } -ParameterFilter { -# $Name -eq 'NewSwitch' -# } - -# $testParams = @{ -# Name = "NewSwitch" -# Type = "External" -# NetAdapterName = @("NIC1", "NIC2") -# AllowManagementOS = $true -# EnableEmbeddedTeaming = $true -# Ensure = "Present" -# } - -# It "Should return present in the get method" { -# (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" -# } - -# It "Should return true in the test method" { -# Test-TargetResource @testParams | Should -Be $true -# } -# } - -# Context "A virtual switch with embedded teaming exists but does not refer to the correct adapters" { -# $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() -# $mockVMSwitch.Name = 'NewSwitch' -# $mockVMSwitch.SwitchType = 'External' -# $mockVMSwitch.AllowManagementOS = $true -# $mockVMSwitch.EmbeddedTeamingEnabled = $true -# $mockVMSwitch.Id = [Guid]::NewGuid() -# $mockVMSwitch.NetAdapterInterfaceDescriptions = @( -# 'Wrong adapter', -# 'Microsoft Network Adapter Multiplexor Driver #2' -# ) - -# Mock -CommandName Get-VMSwitch -MockWith { -# return $mockVMSwitch -# } -ParameterFilter { -# $Name -eq 'NewSwitch' -# } - -# Mock -CommandName Get-NetAdapter -MockWith { -# return @( -# [PSCustomObject]@{ -# Name = 'WrongNic' -# InterfaceDescription = 'Wrong adapter' -# } -# [PSCustomObject]@{ -# Name = 'NIC2' -# InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #2' -# } -# ) -# } - -# $testParams = @{ -# Name = "NewSwitch" -# Type = "External" -# NetAdapterName = @("NIC1", "NIC2") -# AllowManagementOS = $true -# EnableEmbeddedTeaming = $true -# Ensure = "Present" -# } - -# It "Should return present in the get method" { -# (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" -# } - -# It "Should return false in the test method" { -# Test-TargetResource @testParams | Should -Be $false -# } - -# It "Should run the set method without exceptions" { -# Set-TargetResource @testParams -# Assert-MockCalled -CommandName "Remove-VMSwitch" -Times 1 -# Assert-MockCalled -CommandName "New-VMSwitch" -Times 1 -# } -# } - -# Context "A virtual switch with embedded teaming exists but does not use the correct LB algorithm" { -# $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() -# $mockVMSwitch.Name = 'NewSwitch' -# $mockVMSwitch.SwitchType = 'External' -# $mockVMSwitch.AllowManagementOS = $true -# $mockVMSwitch.EmbeddedTeamingEnabled = $true -# $mockVMSwitch.Id = [Guid]::NewGuid() -# $mockVMSwitch.NetAdapterInterfaceDescriptions = @( -# 'Microsoft Network Adapter Multiplexor Driver #1', -# 'Microsoft Network Adapter Multiplexor Driver #2' -# ) - -# Mock -CommandName Get-VMSwitch -MockWith { -# return $mockVMSwitch -# } -ParameterFilter { -# $Name -eq 'NewSwitch' -# } - -# $mockVMSwitchTeam = [Microsoft.HyperV.PowerShell.VMSwitchTeam]::CreateTypeInstance() -# $mockVMSwitchTeam.Name = 'SwitchTeam' -# $mockVMSwitchTeam.LoadBalancingAlgorithm = 'Dynamic' -# $mockVMSwitchTeam.Id = [Guid]::NewGuid() - -# Mock -CommandName Get-VMSwitchTeam -MockWith { -# return $mockVMSwitchTeam -# } - -# Mock -CommandName Get-NetAdapter -MockWith { -# return @( -# [PSCustomObject]@{ -# Name = 'NIC01' -# InterfaceDescription = "Microsoft Network Adapter Multiplexor Driver #1" -# } -# [PSCustomObject]@{ -# Name = 'NIC2' -# InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #2' -# } -# ) -# } - -# $testParams = @{ -# Name = "NewSwitch" -# Type = "External" -# NetAdapterName = @("NIC1", "NIC2") -# AllowManagementOS = $true -# EnableEmbeddedTeaming = $true -# LoadBalancingAlgorithm = 'HyperVPort' -# Ensure = "Present" -# } - -# It "Should return present in the get method" { -# (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" -# } - -# It "Should return false in the test method" { -# Test-TargetResource @testParams | Should -Be $false -# } - -# It "Should run the set method without exceptions" { -# Set-TargetResource @testParams -# Assert-MockCalled -CommandName "Remove-VMSwitch" -Times 1 -# Assert-MockCalled -CommandName "New-VMSwitch" -Times 1 -# } -# } - -# Context "A virtual switch without embedded teaming exists but should use embedded teaming" { -# $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() -# $mockVMSwitch.Name = 'NewSwitch' -# $mockVMSwitch.SwitchType = 'External' -# $mockVMSwitch.AllowManagementOS = $true -# $mockVMSwitch.EmbeddedTeamingEnabled = $false -# $mockVMSwitch.Id = [Guid]::NewGuid() -# $mockVMSwitch.NetAdapterInterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #1' - -# Mock -CommandName Get-VMSwitch -MockWith { -# return $mockVMSwitch -# } -ParameterFilter { -# $Name -eq 'NewSwitch' -# } - -# $testParams = @{ -# Name = "NewSwitch" -# Type = "External" -# NetAdapterName = @("NIC1", "NIC2") -# AllowManagementOS = $true -# EnableEmbeddedTeaming = $true -# BandwidthReservationMode = "NA" -# Ensure = "Present" -# } - -# It "Should return present in the get method" { -# (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" -# } - -# It "Should return false in the test method" { -# Test-TargetResource @testParams | Should -Be $false -# } - -# It "Should run the set method without exceptions" { -# Set-TargetResource @testParams -# Assert-MockCalled -CommandName "Remove-VMSwitch" -Times 1 -# Assert-MockCalled -CommandName "New-VMSwitch" -Times 1 -# } -# } - -# Context "A virtual switch with embedded teaming exists but shouldn't" { -# $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() -# $mockVMSwitch.Name = 'NewSwitch' -# $mockVMSwitch.SwitchType = 'External' -# $mockVMSwitch.AllowManagementOS = $true -# $mockVMSwitch.EmbeddedTeamingEnabled = $true -# $mockVMSwitch.Id = [Guid]::NewGuid() -# $mockVMSwitch.NetAdapterInterfaceDescriptions = @( -# 'Microsoft Network Adapter Multiplexor Driver #1', -# 'Microsoft Network Adapter Multiplexor Driver #2' -# ) - -# Mock -CommandName Get-VMSwitch -MockWith { -# return $mockVMSwitch -# } -ParameterFilter { -# $Name -eq 'NewSwitch' -# } - -# $testParams = @{ -# Name = "NewSwitch" -# Type = "Internal" -# Ensure = "Absent" -# } - -# It "Should return present in the get method" { -# (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" -# } - -# It "Should return false in the test method" { -# Test-TargetResource @testParams | Should -Be $false -# } - -# It "Should run the set method without exceptions" { -# Set-TargetResource @testParams -# Assert-MockCalled -CommandName "Remove-VMSwitch" -Times 1 -# } -# } - -# Context "A virtual switch with embedded teaming does not exist and shouldn't" { -# $script:mockedVMSwitch = $null - -# $testParams = @{ -# Name = "TestSwitch" -# Type = "Internal" -# Ensure = "Absent" -# } - -# It "Should return absent in the get method" { -# (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Absent" -# } - -# It "Should return true in the test method" { -# Test-TargetResource @testParams | Should -Be $true -# } -# } - -# Context "A server is not running Server 2016 and attempts to use embedded teaming" { -# $script:mockedVMSwitch = $null - -# $testParams = @{ -# Name = "TestSwitch" -# Type = "External" -# NetAdapterName = @("NIC1", "NIC2") -# AllowManagementOS = $true -# EnableEmbeddedTeaming = $true -# BandwidthReservationMode = "NA" -# Ensure = "Present" -# } - -# Mock -CommandName Get-OSVersion -MockWith { -# return [Version]::Parse('6.3.9600') -# } - -# It "Should return absent in the get method" { -# (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Absent" -# } - -# It "Should throw an error in the test method" { -# $errorMessage = $script:localizedData.SETServer2016Error - -# {Test-TargetResource @testParams} | Should -Throw $errorMessage -# } - -# It "Should throw an error in the set method" { -# $errorMessage = $script:localizedData.SETServer2016Error - -# {Set-TargetResource @testParams} | Should -Throw $errorMessage -# } -# } -# } -# } -# } -# finally -# { -# Invoke-TestCleanup -# } +$script:dscModuleName = 'HyperVDsc' +$script:dscResourceName = 'DSC_VMSwitch' + +function Invoke-TestSetup +{ + try + { + Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + } + + $script:testEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:dscModuleName ` + -DSCResourceName $script:dscResourceName ` + -ResourceType 'Mof' ` + -TestType 'Unit' + + # Import the stub functions. + Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +} + +function Invoke-TestCleanup +{ + Restore-TestEnvironment -TestEnvironment $script:testEnvironment +} + +Invoke-TestSetup + +try +{ + InModuleScope $script:dscResourceName { + # A helper function to mock a VMSwitch + function New-MockedVMSwitch + { + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [ValidateSet('Default', 'Weight', 'Absolute', 'None', 'NA')] + [System.String] + $BandwidthReservationMode, + + [Parameter()] + [ValidateSet('Dynamic','HyperVPort')] + [System.String] + $LoadBalancingAlgorithm, + + [Parameter()] + [System.Boolean] + $AllowManagementOS = $false + ) + + $mockedVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() + $mockedVMSwitch.Name = $Name + $mockedVMSwitch.SwitchType = 'External' + $mockedVMSwitch.AllowManagementOS = $AllowManagementOS + $mockedVMSwitch.NetAdapterInterfaceDescriptions = 'Microsoft Network Adapter Multiplexor Driver' + + if ($BandwidthReservationMode -ne 'NA') + { + $mockedVMSwitch.BandwidthReservationMode = $BandwidthReservationMode + } + + if ($PSBoundParameters.ContainsKey('LoadBalancingAlgorithm')) + { + $mockedVMSwitch.LoadBalancingAlgorithm = $LoadBalancingAlgorithm + } + + return $mockedVMSwitch + } + + Describe "DSC_VMSwitch" { + <# + Mocks Get-VMSwitch and will return $script:mockedVMSwitch which is + a variable that is created during most It statements to mock a VMSwitch + #> + Mock -CommandName Get-VMSwitch -MockWith { + if ($ErrorAction -eq 'Stop' -and $script:mockedVMSwitch -eq $null) + { + throw [System.Management.Automation.ActionPreferenceStopException]'No switch can be found by given criteria.' + } + + return $script:mockedVMSwitch + } + + <# + Mocks New-VMSwitch and will assign a mocked switch to $script:mockedVMSwitch. This returns $script:mockedVMSwitch + which is a variable that is created during most It statements to mock a VMSwitch + #> + Mock -CommandName New-VMSwitch -MockWith { + param + ( + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String[]] + $NetAdapterName, + + [Parameter()] + [System.String] + $MinimumBandwidthMode = 'NA', + + [Parameter()] + [System.Boolean] + $EnableEmbeddedTeaming, + + [Parameter()] + [System.Boolean] + $AllowManagementOS + ) + + $script:mockedVMSwitch = New-MockedVMSwitch -Name $Name -BandwidthReservationMode $MinimumBandwidthMode -AllowManagementOS $AllowManagementOS + #is SET is enabled mok a VMSwitchTeam + if ($EnableEmbeddedTeaming) + { + $script:mockedVMSwitchTeam = [PSCustomObject]@{ + Name = "TestSwitch" + Id = [Guid]::NewGuid() + TeamingMode = 'SwitchIndependent' + LoadBalancingAlgorithm = 'Dynamic' + } + } + return $script:mockedVMSwitch + } + + Mock -CommandName Get-OSVersion -MockWith { + return @{ + Major = 10 + } + } + + <# + Mocks Remove-VMSwitch and will remove the variable $script:mockedVMSwitch which is + a variable that is created during most It statements to mock a VMSwitch + #> + Mock -CommandName Remove-VMSwitch -MockWith { + $script:mockedVMSwitch = $null + } + + <# + Mocks Get-VMSwitchTeam and will return a moked VMSwitchTeam + #> + Mock -CommandName Get-VMSwitchTeam -MockWith { + return $script:mockedVMSwitchTeam + } + + Mock -CommandName Set-VMSwitchTeam + + # Mocks Get-NetAdapter which returns a simplified network adapter + Mock -CommandName Get-NetAdapter -MockWith { + return @( + [PSCustomObject]@{ + Name = 'NIC1' + InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #1' + } + [PSCustomObject]@{ + Name = 'NIC2' + InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #2' + } + ) + } + + # 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 + } + + Context "A virtual switch with embedded teaming does not exist but should" { + $script:mockedVMSwitch = $null + + $testParams = @{ + Name = "TestSwitch" + Type = "External" + NetAdapterName = @("NIC1", "NIC2") + AllowManagementOS = $true + EnableEmbeddedTeaming = $true + BandwidthReservationMode = "NA" + Ensure = "Present" + } + + It "Should return absent in the get method" { + (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Absent" + } + + It "Should return false in the test method" { + Test-TargetResource @testParams | Should -Be $false + } + + It "Should run the set method without exceptions" { + Set-TargetResource @testParams + Assert-MockCalled -CommandName "New-VMSwitch" -Times 1 + } + } + + Context "A virtual switch with embedded teaming exists and should" { + $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() + $mockVMSwitch.Name = 'NewSwitch' + $mockVMSwitch.SwitchType = 'External' + $mockVMSwitch.AllowManagementOS = $true + $mockVMSwitch.EmbeddedTeamingEnabled = $true + $mockVMSwitch.Id = [Guid]::NewGuid() + $mockVMSwitch.NetAdapterInterfaceDescriptions = @( + 'Microsoft Network Adapter Multiplexor Driver #1', + 'Microsoft Network Adapter Multiplexor Driver #2' + ) + + Mock -CommandName Get-VMSwitch -MockWith { + return $mockVMSwitch + } -ParameterFilter { + $Name -eq 'NewSwitch' + } + + $testParams = @{ + Name = "NewSwitch" + Type = "External" + NetAdapterName = @("NIC1", "NIC2") + AllowManagementOS = $true + EnableEmbeddedTeaming = $true + Ensure = "Present" + } + + It "Should return present in the get method" { + (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" + } + + It "Should return true in the test method" { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context "A virtual switch with embedded teaming exists but does not refer to the correct adapters" { + $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() + $mockVMSwitch.Name = 'NewSwitch' + $mockVMSwitch.SwitchType = 'External' + $mockVMSwitch.AllowManagementOS = $true + $mockVMSwitch.EmbeddedTeamingEnabled = $true + $mockVMSwitch.Id = [Guid]::NewGuid() + $mockVMSwitch.NetAdapterInterfaceDescriptions = @( + 'Wrong adapter', + 'Microsoft Network Adapter Multiplexor Driver #2' + ) + + Mock -CommandName Get-VMSwitch -MockWith { + return $mockVMSwitch + } -ParameterFilter { + $Name -eq 'NewSwitch' + } + + Mock -CommandName Get-NetAdapter -MockWith { + return @( + [PSCustomObject]@{ + Name = 'WrongNic' + InterfaceDescription = 'Wrong adapter' + } + [PSCustomObject]@{ + Name = 'NIC2' + InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #2' + } + ) + } + + $testParams = @{ + Name = "NewSwitch" + Type = "External" + NetAdapterName = @("NIC1", "NIC2") + AllowManagementOS = $true + EnableEmbeddedTeaming = $true + Ensure = "Present" + } + + It "Should return present in the get method" { + (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" + } + + It "Should return false in the test method" { + Test-TargetResource @testParams | Should -Be $false + } + + It "Should run the set method without exceptions" { + Set-TargetResource @testParams + Assert-MockCalled -CommandName "Remove-VMSwitch" -Times 1 + Assert-MockCalled -CommandName "New-VMSwitch" -Times 1 + } + } + + Context "A virtual switch with embedded teaming exists but does not use the correct LB algorithm" { + $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() + $mockVMSwitch.Name = 'NewSwitch' + $mockVMSwitch.SwitchType = 'External' + $mockVMSwitch.AllowManagementOS = $true + $mockVMSwitch.EmbeddedTeamingEnabled = $true + $mockVMSwitch.Id = [Guid]::NewGuid() + $mockVMSwitch.NetAdapterInterfaceDescriptions = @( + 'Microsoft Network Adapter Multiplexor Driver #1', + 'Microsoft Network Adapter Multiplexor Driver #2' + ) + + Mock -CommandName Get-VMSwitch -MockWith { + return $mockVMSwitch + } -ParameterFilter { + $Name -eq 'NewSwitch' + } + + $mockVMSwitchTeam = [Microsoft.HyperV.PowerShell.VMSwitchTeam]::CreateTypeInstance() + $mockVMSwitchTeam.Name = 'SwitchTeam' + $mockVMSwitchTeam.LoadBalancingAlgorithm = 'Dynamic' + $mockVMSwitchTeam.Id = [Guid]::NewGuid() + + Mock -CommandName Get-VMSwitchTeam -MockWith { + return $mockVMSwitchTeam + } + + Mock -CommandName Get-NetAdapter -MockWith { + return @( + [PSCustomObject]@{ + Name = 'NIC01' + InterfaceDescription = "Microsoft Network Adapter Multiplexor Driver #1" + } + [PSCustomObject]@{ + Name = 'NIC2' + InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #2' + } + ) + } + + $testParams = @{ + Name = "NewSwitch" + Type = "External" + NetAdapterName = @("NIC1", "NIC2") + AllowManagementOS = $true + EnableEmbeddedTeaming = $true + LoadBalancingAlgorithm = 'HyperVPort' + Ensure = "Present" + } + + It "Should return present in the get method" { + (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" + } + + It "Should return false in the test method" { + Test-TargetResource @testParams | Should -Be $false + } + + It "Should run the set method without exceptions" { + Set-TargetResource @testParams + Assert-MockCalled -CommandName "Remove-VMSwitch" -Times 1 + Assert-MockCalled -CommandName "New-VMSwitch" -Times 1 + } + } + + Context "A virtual switch without embedded teaming exists but should use embedded teaming" { + $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() + $mockVMSwitch.Name = 'NewSwitch' + $mockVMSwitch.SwitchType = 'External' + $mockVMSwitch.AllowManagementOS = $true + $mockVMSwitch.EmbeddedTeamingEnabled = $false + $mockVMSwitch.Id = [Guid]::NewGuid() + $mockVMSwitch.NetAdapterInterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #1' + + Mock -CommandName Get-VMSwitch -MockWith { + return $mockVMSwitch + } -ParameterFilter { + $Name -eq 'NewSwitch' + } + + $testParams = @{ + Name = "NewSwitch" + Type = "External" + NetAdapterName = @("NIC1", "NIC2") + AllowManagementOS = $true + EnableEmbeddedTeaming = $true + BandwidthReservationMode = "NA" + Ensure = "Present" + } + + It "Should return present in the get method" { + (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" + } + + It "Should return false in the test method" { + Test-TargetResource @testParams | Should -Be $false + } + + It "Should run the set method without exceptions" { + Set-TargetResource @testParams + Assert-MockCalled -CommandName "Remove-VMSwitch" -Times 1 + Assert-MockCalled -CommandName "New-VMSwitch" -Times 1 + } + } + + Context "A virtual switch with embedded teaming exists but shouldn't" { + $mockVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() + $mockVMSwitch.Name = 'NewSwitch' + $mockVMSwitch.SwitchType = 'External' + $mockVMSwitch.AllowManagementOS = $true + $mockVMSwitch.EmbeddedTeamingEnabled = $true + $mockVMSwitch.Id = [Guid]::NewGuid() + $mockVMSwitch.NetAdapterInterfaceDescriptions = @( + 'Microsoft Network Adapter Multiplexor Driver #1', + 'Microsoft Network Adapter Multiplexor Driver #2' + ) + + Mock -CommandName Get-VMSwitch -MockWith { + return $mockVMSwitch + } -ParameterFilter { + $Name -eq 'NewSwitch' + } + + $testParams = @{ + Name = "NewSwitch" + Type = "Internal" + Ensure = "Absent" + } + + It "Should return present in the get method" { + (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Present" + } + + It "Should return false in the test method" { + Test-TargetResource @testParams | Should -Be $false + } + + It "Should run the set method without exceptions" { + Set-TargetResource @testParams + Assert-MockCalled -CommandName "Remove-VMSwitch" -Times 1 + } + } + + Context "A virtual switch with embedded teaming does not exist and shouldn't" { + $script:mockedVMSwitch = $null + + $testParams = @{ + Name = "TestSwitch" + Type = "Internal" + Ensure = "Absent" + } + + It "Should return absent in the get method" { + (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Absent" + } + + It "Should return true in the test method" { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context "A server is not running Server 2016 and attempts to use embedded teaming" { + $script:mockedVMSwitch = $null + + $testParams = @{ + Name = "TestSwitch" + Type = "External" + NetAdapterName = @("NIC1", "NIC2") + AllowManagementOS = $true + EnableEmbeddedTeaming = $true + BandwidthReservationMode = "NA" + Ensure = "Present" + } + + Mock -CommandName Get-OSVersion -MockWith { + return [Version]::Parse('6.3.9600') + } + + It "Should return absent in the get method" { + (Get-TargetResource -Name $testParams.Name -Type $testParams.Type).Ensure | Should -Be "Absent" + } + + It "Should throw an error in the test method" { + $errorMessage = $script:localizedData.SETServer2016Error + + {Test-TargetResource @testParams} | Should -Throw $errorMessage + } + + It "Should throw an error in the set method" { + $errorMessage = $script:localizedData.SETServer2016Error + + {Set-TargetResource @testParams} | Should -Throw $errorMessage + } + } + } + } +} +finally +{ + Invoke-TestCleanup +} diff --git a/tests/Unit/DSC_VMSwitch_Id.Tests.ps1 b/tests/Unit/DSC_VMSwitch_Id.Tests.ps1 index e302833..f63b968 100644 --- a/tests/Unit/DSC_VMSwitch_Id.Tests.ps1 +++ b/tests/Unit/DSC_VMSwitch_Id.Tests.ps1 @@ -1,376 +1,376 @@ -# $script:dscModuleName = 'HyperVDsc' -# $script:dscResourceName = 'DSC_VMSwitch' - -# function Invoke-TestSetup -# { -# try -# { -# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' -# } -# catch [System.IO.FileNotFoundException] -# { -# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' -# } - -# $script:testEnvironment = Initialize-TestEnvironment ` -# -DSCModuleName $script:dscModuleName ` -# -DSCResourceName $script:dscResourceName ` -# -ResourceType 'Mof' ` -# -TestType 'Unit' - -# # Import the stub functions. -# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -# } - -# function Invoke-TestCleanup -# { -# Restore-TestEnvironment -TestEnvironment $script:testEnvironment -# } - -# Invoke-TestSetup - -# try -# { -# InModuleScope $script:dscResourceName { -# # A helper function to mock a VMSwitch -# function New-MockedVMSwitch -# { -# param ( -# [Parameter(Mandatory = $true)] -# [System.String] -# $Name, - -# [Parameter()] -# [ValidateNotNullOrEmpty()] -# [Guid] -# $Id -# ) - -# $mockedVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() -# $mockedVMSwitch.Name = $Name -# $mockedVMSwitch.SwitchType = 'External' -# $mockedVMSwitch.AllowManagementOS = $true -# $mockedVMSwitch.EmbeddedTeamingEnabled = $true -# $mockedVMSwitch.BandwidthReservationMode = 'Default' -# $mockedVMSwitch.NetAdapterInterfaceDescriptions = @( -# 'Microsoft Network Adapter Multiplexor Driver #1', -# 'Microsoft Network Adapter Multiplexor Driver #2' -# ) - -# if ($PSBoundParameters.ContainsKey('Id')) -# { -# $mockedVMSwitch.Id = $Id -# } -# else -# { -# $mockedVMSwitch.Id = New-Guid -# } - -# return $mockedVMSwitch -# } - -# # 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 -CommandName Get-VMSwitch -MockWith { -# return $script:MockedVMSwitch -# } - -# Mock -CommandName Get-NetAdapter -MockWith { -# return @( -# [PSCustomObject]@{ -# Name = 'NIC1' -# InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #1' -# } -# [PSCustomObject]@{ -# Name = 'NIC2' -# InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #2' -# } -# ) -# } - -# Mock -CommandName Get-VMSwitchTeam -MockWith { -# return [PSCustomObject]@{ -# Name = 'TestTeam' -# Id = New-Guid -# NetAdapterInterfaceDescription = @("Microsoft Network Adapter Multiplexor Driver #1", "Microsoft Network Adapter Multiplexor Driver #2") -# TeamingMode = 'SwitchIndependent' -# LoadBalancingAlgorithm = 'HyperVPort' -# } -# } - -# Mock -CommandName Remove-VMSwitch -MockWith { -# $script:mockedVMSwitch = $null -# } - -# Mock -CommandName New-VMSwitch -MockWith { -# param -# ( -# [Parameter()] -# [System.String] -# $Name, - -# [Parameter()] -# [System.String[]] -# $NetAdapterName, - -# [Parameter()] -# [System.String] -# $MinimumBandwidthMode, - -# [Parameter()] -# [System.Boolean] -# $AllowManagementOS, - -# [Parameter()] -# [System.String] -# $SwitchType, - -# [Parameter()] -# [System.Boolean] -# $EnableEmbeddedTeaming, - -# [Parameter()] -# [Guid] -# $Id -# ) - -# if ($PSBoundParameters.ContainsKey('Id')) -# { -# $script:MockedVMSwitch = New-MockedVMSwitch -Name $Name -Id $id -# } -# else -# { -# $script:MockedVMSwitch = New-MockedVMSwitch -Name $Name -# } -# } - -# Mock -CommandName Get-OSVersion -MockWith { -# [PSCustomObject]@{ -# Major = 10 -# Minor = 0 -# Build = 14393 -# Revision = 0 -# MajorRevision = 0 -# MinorRevision = 0 -# } -# } - -# Describe 'DSC_VMSwitch\Get-TargetResource' -Tag 'Get' { - -# Context 'When the system is in the desired state (VMSwitch has the desired Id)' { -# $script:MockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' - -# It 'Should return "present"' { -# (Get-TargetResource -Name 'TestSwitch' -Type 'External').Ensure | Should -Be 'Present' -# Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 -# Assert-MockCalled -CommandName "Get-VMSwitchTeam" -Times 1 -# } -# } - -# Context 'When the system is not in the desired state (VMSwitch has not the desired Id)' { - -# $script:mockedVMSwitch = $null - -# It 'Should return "absent"' { -# (Get-TargetResource -Name 'TestSwitch' -Type 'External').Ensure | Should -Be 'Absent' -# Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 -# Assert-MockCalled -CommandName "Get-VMSwitchTeam" -Times 0 -# } -# } -# } - -# Describe 'DSC_VMSwitch\Set-TargetResource' -Tag 'Set' { - -# Context 'When the system is in the desired state (VMSwitch has the desired Id)' { -# $desiredVMSwitchID = New-Guid - -# $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' -Id $desiredVMSwitchID - -# $testParams = @{ -# Name = 'TestSwitch' -# Type = 'External' -# NetAdapterName = @('NIC1', 'NIC2') -# AllowManagementOS = $true -# EnableEmbeddedTeaming = $true -# Ensure = 'Present' -# Id = $desiredVMSwitchID -# } - -# It 'Should run without without exceptions' { -# {Set-TargetResource @testParams} | Should -Not -throw -# Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 -# Assert-MockCalled -CommandName 'Get-NetAdapter' -Times 1 -# } -# } - -# Context 'When the system is not in the desired state (VMSwitch has not the desired Id)' { - -# $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' - -# $testParams = @{ -# Name = 'TestSwitch' -# Type = 'External' -# NetAdapterName = @('NIC1', 'NIC2') -# AllowManagementOS = $true -# EnableEmbeddedTeaming = $true -# Ensure = 'Present' -# Id = New-Guid -# } - -# It 'Should run without exception while re-creating the VMSwitch' { -# {Set-TargetResource @testParams} | Should -Not -throw -# Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 -# Assert-MockCalled -CommandName 'Get-NetAdapter' -Times 1 -# Assert-MockCalled -CommandName 'Remove-VMSwitch' -Times 1 -# Assert-MockCalled -CommandName 'New-VMSwitch' -Times 1 -# } -# } - -# Context 'When the specified value for Id parameter is not a GUID' { - -# $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' - -# $testParams = @{ -# Name = 'TestSwitch' -# Type = 'External' -# NetAdapterName = @('NIC1', 'NIC2') -# AllowManagementOS = $true -# EnableEmbeddedTeaming = $true -# Ensure = 'Present' -# Id = '123' -# } - -# It 'Should throw "The VMSwitch Id must be in GUID format!"' { -# {Set-TargetResource @testParams} | Should -Throw 'The VMSwitch Id must be in GUID format!' -# } -# } - -# Context 'When the system is not running Server 2016' { - -# $desiredVMSwitchID = New-Guid - -# $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' -Id $desiredVMSwitchID - -# $testParams = @{ -# Name = 'TestSwitch' -# Type = 'External' -# NetAdapterName = 'NIC1' -# AllowManagementOS = $true -# EnableEmbeddedTeaming = $false -# Ensure = 'Present' -# Id = $desiredVMSwitchID -# } - -# Mock -CommandName Get-OSVersion -MockWith { -# return [Version]::Parse('6.3.9600') -# } - -# $errorMessage = $script:localizedData.VMSwitchIDServer2016Error - -# It 'Should throw "VMSwitchIDServer2016Error"' { -# {Set-TargetResource @testParams} | Should -Throw $errorMessage -# } -# } -# } - -# Describe 'DSC_VMSwitch\Test-TargetResource' -Tag 'Test' { -# Context 'When the system is in the desired state (VMSwitch has the desired Id)' { - -# $desiredVMSwitchID = New-Guid - -# $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' -Id $desiredVMSwitchID - -# $testParams = @{ -# Name = 'TestSwitch' -# Type = 'External' -# NetAdapterName = @('NIC1', 'NIC2') -# AllowManagementOS = $true -# EnableEmbeddedTeaming = $true -# Ensure = 'Present' -# Id = $desiredVMSwitchID -# } - -# It 'Should return $true' { -# {Test-TargetResource @testParams} | Should -Not -throw -# Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 -# Assert-MockCalled -CommandName 'Get-NetAdapter' -Times 1 -# } -# } - -# Context 'When the system is not in the desired state (VMSwitch has not the desired Id)' { - -# $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' - -# $testParams = @{ -# Name = 'TestSwitch' -# Type = 'External' -# NetAdapterName = @('NIC1', 'NIC2') -# AllowManagementOS = $true -# EnableEmbeddedTeaming = $true -# Ensure = 'Present' -# Id = New-Guid -# } - -# It 'Should return $false' { -# {Test-TargetResource @testParams} | Should -Not -throw -# Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 -# Assert-MockCalled -CommandName 'Get-NetAdapter' -Times 1 -# } -# } - -# Context 'When the specified value for Id parameter is not a GUID' { - -# $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' - -# $testParams = @{ -# Name = 'TestSwitch' -# Type = 'External' -# NetAdapterName = @('NIC1', 'NIC2') -# AllowManagementOS = $true -# EnableEmbeddedTeaming = $true -# Ensure = 'Present' -# Id = '123' -# } - -# It 'Should throw "The VMSwitch Id must be in GUID format!"' { -# {Test-TargetResource @testParams} | Should -Throw 'The VMSwitch Id must be in GUID format!' -# } -# } - -# Context 'When the system is not running Server 2016' { - -# $desiredVMSwitchID = New-Guid - -# $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' -Id $desiredVMSwitchID - -# $testParams = @{ -# Name = 'TestSwitch' -# Type = 'External' -# NetAdapterName = 'NIC1' -# AllowManagementOS = $true -# EnableEmbeddedTeaming = $false -# Ensure = 'Present' -# Id = $desiredVMSwitchID -# } - -# Mock -CommandName Get-OSVersion -MockWith { -# return [Version]::Parse('6.3.9600') -# } - -# $errorMessage = $script:localizedData.VMSwitchIDServer2016Error - -# It 'Should throw "VMSwitchIDServer2016Error"' { -# {Test-TargetResource @testParams} | Should -Throw $errorMessage -# } -# } - -# } -# } -# } -# finally -# { -# Invoke-TestCleanup -# } +$script:dscModuleName = 'HyperVDsc' +$script:dscResourceName = 'DSC_VMSwitch' + +function Invoke-TestSetup +{ + try + { + Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + } + + $script:testEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:dscModuleName ` + -DSCResourceName $script:dscResourceName ` + -ResourceType 'Mof' ` + -TestType 'Unit' + + # Import the stub functions. + Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +} + +function Invoke-TestCleanup +{ + Restore-TestEnvironment -TestEnvironment $script:testEnvironment +} + +Invoke-TestSetup + +try +{ + InModuleScope $script:dscResourceName { + # A helper function to mock a VMSwitch + function New-MockedVMSwitch + { + param ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [Guid] + $Id + ) + + $mockedVMSwitch = [Microsoft.HyperV.PowerShell.VMSwitch]::CreateTypeInstance() + $mockedVMSwitch.Name = $Name + $mockedVMSwitch.SwitchType = 'External' + $mockedVMSwitch.AllowManagementOS = $true + $mockedVMSwitch.EmbeddedTeamingEnabled = $true + $mockedVMSwitch.BandwidthReservationMode = 'Default' + $mockedVMSwitch.NetAdapterInterfaceDescriptions = @( + 'Microsoft Network Adapter Multiplexor Driver #1', + 'Microsoft Network Adapter Multiplexor Driver #2' + ) + + if ($PSBoundParameters.ContainsKey('Id')) + { + $mockedVMSwitch.Id = $Id + } + else + { + $mockedVMSwitch.Id = New-Guid + } + + return $mockedVMSwitch + } + + # 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 -CommandName Get-VMSwitch -MockWith { + return $script:MockedVMSwitch + } + + Mock -CommandName Get-NetAdapter -MockWith { + return @( + [PSCustomObject]@{ + Name = 'NIC1' + InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #1' + } + [PSCustomObject]@{ + Name = 'NIC2' + InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver #2' + } + ) + } + + Mock -CommandName Get-VMSwitchTeam -MockWith { + return [PSCustomObject]@{ + Name = 'TestTeam' + Id = New-Guid + NetAdapterInterfaceDescription = @("Microsoft Network Adapter Multiplexor Driver #1", "Microsoft Network Adapter Multiplexor Driver #2") + TeamingMode = 'SwitchIndependent' + LoadBalancingAlgorithm = 'HyperVPort' + } + } + + Mock -CommandName Remove-VMSwitch -MockWith { + $script:mockedVMSwitch = $null + } + + Mock -CommandName New-VMSwitch -MockWith { + param + ( + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.String[]] + $NetAdapterName, + + [Parameter()] + [System.String] + $MinimumBandwidthMode, + + [Parameter()] + [System.Boolean] + $AllowManagementOS, + + [Parameter()] + [System.String] + $SwitchType, + + [Parameter()] + [System.Boolean] + $EnableEmbeddedTeaming, + + [Parameter()] + [Guid] + $Id + ) + + if ($PSBoundParameters.ContainsKey('Id')) + { + $script:MockedVMSwitch = New-MockedVMSwitch -Name $Name -Id $id + } + else + { + $script:MockedVMSwitch = New-MockedVMSwitch -Name $Name + } + } + + Mock -CommandName Get-OSVersion -MockWith { + [PSCustomObject]@{ + Major = 10 + Minor = 0 + Build = 14393 + Revision = 0 + MajorRevision = 0 + MinorRevision = 0 + } + } + + Describe 'DSC_VMSwitch\Get-TargetResource' -Tag 'Get' { + + Context 'When the system is in the desired state (VMSwitch has the desired Id)' { + $script:MockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' + + It 'Should return "present"' { + (Get-TargetResource -Name 'TestSwitch' -Type 'External').Ensure | Should -Be 'Present' + Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 + Assert-MockCalled -CommandName "Get-VMSwitchTeam" -Times 1 + } + } + + Context 'When the system is not in the desired state (VMSwitch has not the desired Id)' { + + $script:mockedVMSwitch = $null + + It 'Should return "absent"' { + (Get-TargetResource -Name 'TestSwitch' -Type 'External').Ensure | Should -Be 'Absent' + Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 + Assert-MockCalled -CommandName "Get-VMSwitchTeam" -Times 0 + } + } + } + + Describe 'DSC_VMSwitch\Set-TargetResource' -Tag 'Set' { + + Context 'When the system is in the desired state (VMSwitch has the desired Id)' { + $desiredVMSwitchID = New-Guid + + $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' -Id $desiredVMSwitchID + + $testParams = @{ + Name = 'TestSwitch' + Type = 'External' + NetAdapterName = @('NIC1', 'NIC2') + AllowManagementOS = $true + EnableEmbeddedTeaming = $true + Ensure = 'Present' + Id = $desiredVMSwitchID + } + + It 'Should run without without exceptions' { + {Set-TargetResource @testParams} | Should -Not -throw + Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 + Assert-MockCalled -CommandName 'Get-NetAdapter' -Times 1 + } + } + + Context 'When the system is not in the desired state (VMSwitch has not the desired Id)' { + + $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' + + $testParams = @{ + Name = 'TestSwitch' + Type = 'External' + NetAdapterName = @('NIC1', 'NIC2') + AllowManagementOS = $true + EnableEmbeddedTeaming = $true + Ensure = 'Present' + Id = New-Guid + } + + It 'Should run without exception while re-creating the VMSwitch' { + {Set-TargetResource @testParams} | Should -Not -throw + Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 + Assert-MockCalled -CommandName 'Get-NetAdapter' -Times 1 + Assert-MockCalled -CommandName 'Remove-VMSwitch' -Times 1 + Assert-MockCalled -CommandName 'New-VMSwitch' -Times 1 + } + } + + Context 'When the specified value for Id parameter is not a GUID' { + + $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' + + $testParams = @{ + Name = 'TestSwitch' + Type = 'External' + NetAdapterName = @('NIC1', 'NIC2') + AllowManagementOS = $true + EnableEmbeddedTeaming = $true + Ensure = 'Present' + Id = '123' + } + + It 'Should throw "The VMSwitch Id must be in GUID format!"' { + {Set-TargetResource @testParams} | Should -Throw 'The VMSwitch Id must be in GUID format!' + } + } + + Context 'When the system is not running Server 2016' { + + $desiredVMSwitchID = New-Guid + + $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' -Id $desiredVMSwitchID + + $testParams = @{ + Name = 'TestSwitch' + Type = 'External' + NetAdapterName = 'NIC1' + AllowManagementOS = $true + EnableEmbeddedTeaming = $false + Ensure = 'Present' + Id = $desiredVMSwitchID + } + + Mock -CommandName Get-OSVersion -MockWith { + return [Version]::Parse('6.3.9600') + } + + $errorMessage = $script:localizedData.VMSwitchIDServer2016Error + + It 'Should throw "VMSwitchIDServer2016Error"' { + {Set-TargetResource @testParams} | Should -Throw $errorMessage + } + } + } + + Describe 'DSC_VMSwitch\Test-TargetResource' -Tag 'Test' { + Context 'When the system is in the desired state (VMSwitch has the desired Id)' { + + $desiredVMSwitchID = New-Guid + + $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' -Id $desiredVMSwitchID + + $testParams = @{ + Name = 'TestSwitch' + Type = 'External' + NetAdapterName = @('NIC1', 'NIC2') + AllowManagementOS = $true + EnableEmbeddedTeaming = $true + Ensure = 'Present' + Id = $desiredVMSwitchID + } + + It 'Should return $true' { + {Test-TargetResource @testParams} | Should -Not -throw + Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 + Assert-MockCalled -CommandName 'Get-NetAdapter' -Times 1 + } + } + + Context 'When the system is not in the desired state (VMSwitch has not the desired Id)' { + + $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' + + $testParams = @{ + Name = 'TestSwitch' + Type = 'External' + NetAdapterName = @('NIC1', 'NIC2') + AllowManagementOS = $true + EnableEmbeddedTeaming = $true + Ensure = 'Present' + Id = New-Guid + } + + It 'Should return $false' { + {Test-TargetResource @testParams} | Should -Not -throw + Assert-MockCalled -CommandName "Get-VMSwitch" -Times 1 + Assert-MockCalled -CommandName 'Get-NetAdapter' -Times 1 + } + } + + Context 'When the specified value for Id parameter is not a GUID' { + + $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' + + $testParams = @{ + Name = 'TestSwitch' + Type = 'External' + NetAdapterName = @('NIC1', 'NIC2') + AllowManagementOS = $true + EnableEmbeddedTeaming = $true + Ensure = 'Present' + Id = '123' + } + + It 'Should throw "The VMSwitch Id must be in GUID format!"' { + {Test-TargetResource @testParams} | Should -Throw 'The VMSwitch Id must be in GUID format!' + } + } + + Context 'When the system is not running Server 2016' { + + $desiredVMSwitchID = New-Guid + + $script:mockedVMSwitch = New-MockedVMSwitch -Name 'TestSwitch' -Id $desiredVMSwitchID + + $testParams = @{ + Name = 'TestSwitch' + Type = 'External' + NetAdapterName = 'NIC1' + AllowManagementOS = $true + EnableEmbeddedTeaming = $false + Ensure = 'Present' + Id = $desiredVMSwitchID + } + + Mock -CommandName Get-OSVersion -MockWith { + return [Version]::Parse('6.3.9600') + } + + $errorMessage = $script:localizedData.VMSwitchIDServer2016Error + + It 'Should throw "VMSwitchIDServer2016Error"' { + {Test-TargetResource @testParams} | Should -Throw $errorMessage + } + } + + } + } +} +finally +{ + Invoke-TestCleanup +} diff --git a/tests/Unit/DSC_VhdFileDirectory.Tests.ps1 b/tests/Unit/DSC_VhdFileDirectory.Tests.ps1 index 160f989..41a9a66 100644 --- a/tests/Unit/DSC_VhdFileDirectory.Tests.ps1 +++ b/tests/Unit/DSC_VhdFileDirectory.Tests.ps1 @@ -1,531 +1,531 @@ -# $script:dscModuleName = 'HyperVDsc' -# $script:dscResourceName = 'DSC_VhdFileDirectory' - -# function Invoke-TestSetup -# { -# try -# { -# Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' -# } -# catch [System.IO.FileNotFoundException] -# { -# throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' -# } - -# $script:testEnvironment = Initialize-TestEnvironment ` -# -DSCModuleName $script:dscModuleName ` -# -DSCResourceName $script:dscResourceName ` -# -ResourceType 'Mof' ` -# -TestType 'Unit' - -# # Import the stub functions. -# Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force -# } - -# function Invoke-TestCleanup -# { -# Restore-TestEnvironment -TestEnvironment $script:testEnvironment -# } - -# Invoke-TestSetup - -# try -# { -# InModuleScope $script:dscResourceName { - -# #region Functions, Variables and Mocks -# function Get-FreeDriveLetter -# { -# [CmdletBinding()] -# param() - -# $upperCaseChars = 67..90 | ForEach-Object { [char]$_ } -# $driveLettersInUse = Get-PsDrive | Where-Object -FilterScript { -# $upperCaseChars -contains $_.name -# } | Select-Object -ExpandProperty Name - -# foreach ($char in $upperCaseChars) -# { -# if ($driveLettersInUse -notcontains $char) -# { -# Write-Verbose "Selecting $char to use as VhdDriveLetter" - -# return $char -# break -# } -# } -# } - -# function New-TestDriveLayout -# { -# [CmdletBinding(SupportsShouldProcess, ConfirmImpact = "Medium")] -# param( -# [Parameter()] -# [System.String] -# $DriveLetter -# ) - -# # Source file structure -# New-item -Path TestDrive:\VhdExists.vhdx -# 'TestFile1' | Out-File TestDrive:\FileExists.txt -# 'TestFile2' | Out-File TestDrive:\FileExists2.txt -# 'TestFile3' | Out-File TestDrive:\FileExists3.txt -# New-Item -Path TestDrive:\SourceDirectoryExists -ItemType Directory -# New-Item -Path TestDrive:\SourceDirectoryExists2 -ItemType Directory -# 'Some Text' | Out-File TestDrive:\SourceDirectoryExists\File1.txt -# 'Some More Text' | Out-File TestDrive:\SourceDirectoryExists2\File2.txt - -# # VhdRoot structure -# New-Item -Path TestDrive:\MockVhdRoot -ItemType Directory -# New-Item -Path TestDrive:\MockVhdRoot\DestinationDirectoryExists -ItemType Directory -# Copy-Item -Path TestDrive:\FileExists.txt -Destination TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileExists.txt -# Copy-Item -Path TestDrive:\FileExists2.txt -Destination TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileExists2.txt -# Copy-Item -Path TestDrive:\SourceDirectoryExists TestDrive:\DestinationDirectoryExists\SourceDirectory -Recurse -# (Get-Item TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileExists2.txt).Attributes = '' - -# # ShouldProcess supported by New-PsDrive -# New-PSDrive -PSProvider FileSystem -Name $DriveLetter -Root TestDrive:\MockVhdRoot -scope 1 -# } - -# $script:vhdDriveLetter = Get-FreeDriveLetter - -# # function Mount-Vhd {} -# # function Dismount-Vhd {} -# # function Get-Disk {} -# # function Get-Partition {} -# # function Get-Volume {} - -# $script:dscFileDirClassName = 'DSC_FileDirectoryConfiguration' -# $script:dscNamespace = 'root/microsoft/windows/desiredstateconfiguration' - -# Mock -CommandName Mount-Vhd { [PSCustomObject] @{ Path = 'TestDrive:\VhdExists.vhdx' } } - -# Mock -CommandName Dismount-Vhd { } - -# Mock -CommandName Get-Disk { -# New-CimInstance -ClassName MSFT_Disk -Namespace root/Microsoft/Windows/Storage -ClientOnly -# } - -# Mock -CommandName Get-Partition { -# New-CimInstance -ClassName DSC_Partitions -Namespace ROOT/Microsoft/Windows/Storage -ClientOnly | -# Add-Member -MemberType NoteProperty -Name Type -Value 'Mocked' -Force -PassThru | -# Add-Member -MemberType NoteProperty -Name DriveLetter -Value $script:vhdDriveLetter -PassThru -# } - -# Mock -CommandName Get-Volume { -# New-CimInstance -ClassName DSC_Volumes -Namespace ROOT/Microsoft/Windows/Storage -ClientOnly | -# Add-Member -MemberType NoteProperty -Name DriveLetter -Value $script:vhdDriveLetter -PassThru -# } - -# Mock -CommandName Get-Module { -# $true -# } -ParameterFilter { $Name -and $Name -eq "Hyper-V" } - -# #endregion - -# Describe 'DSC_VhdFileDirectory\Get-TargetResource' -Tag 'Get' { - -# BeforeAll { -# New-TestDriveLayout -DriveLetter $script:vhdDriveLetter -# } - -# AfterAll { -# Remove-PSDrive $script:vhdDriveLetter -ErrorAction SilentlyContinue -# } - -# It 'Should return a [System.Collections.Hashtable] object type' { -# $fdProperties = @{ -# SourcePath = 'TestDrive:\FileExists.txt' -# DestinationPath = '\DestinationDirectoryExists\' -# Type = 'File' -# Ensure = 'Present' -# } - -# $fileDirectory = New-CimInstance -Property $fdProperties -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -# $result = Get-TargetResource -VhdPath TestDrive:\VhdExists.vhdx -FileDirectory $fileDirectory - -# $result -is [System.Collections.Hashtable] | -# Should -Be $true -# } - -# #region Testcases for Get-TargetResource -# $testCases_Get = @( -# @{ -# TestName = 'VhdFile exists, Source File exists, Destination File exists' -# FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\FileExists.txt' -# DestinationPath = 'DestinationDirectoryExists\FileExists.txt' -# Type = 'File' -# Ensure = 'Present' -# } -# VhdPath = 'TestDrive:\VhdExists.vhdx' -# ExpectedResult = @{ -# FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# DestinationPath = $script:vhdDriveLetter + ':\DestinationDirectoryExists\FileExists.txt' -# Ensure = 'Present' -# } -# VhdPath = 'TestDrive:\VhdExists.vhdx' -# } -# } -# @{ -# TestName = 'VhdFile exists, Source File exists, Destination File does not exist' -# FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\FileExists.txt' -# DestinationPath = 'DestinationDirectoryExists\DoesNotExist.txt' -# Type = 'File' -# Ensure = 'Present' -# } -# VhdPath = 'TestDrive:\VhdExists.vhdx' -# ExpectedResult = @{ -# FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# DestinationPath = $script:vhdDriveLetter + ':\DestinationDirectoryExists\DoesNotExist.txt' -# Ensure = 'Absent' -# } -# VhdPath = 'TestDrive:\VhdExists.vhdx' -# } -# } -# @{ -# TestName = 'VhdFile exists, Source File does not exist, Destination File exists' -# FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\DoesNotExist.txt' -# DestinationPath = 'DestinationDirectoryExists\FileExists.txt' -# Type = 'File' -# Ensure = 'Present' -# } -# VhdPath = 'TestDrive:\VhdExists.vhdx' -# ExpectedResult = @{ -# FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# DestinationPath = $script:vhdDriveLetter + ':\DestinationDirectoryExists\FileExists.txt' -# Ensure = 'Present' -# } -# VhdPath = 'TestDrive:\VhdExists.vhdx' -# } -# } -# @{ -# TestName = 'VhdFile exists, Source File does not exist, Destination File does not exist' -# FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\DoesNotExist.txt' -# DestinationPath = 'DestinationDirectoryExists\DoesNotExist.txt' -# Type = 'File' -# Ensure = 'Present' -# } -# VhdPath = 'TestDrive:\VhdExists.vhdx' -# ExpectedResult = @{ -# FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# DestinationPath = $script:vhdDriveLetter + ':\DestinationDirectoryExists\DoesNotExist.txt' -# Ensure = 'Absent' -# } -# VhdPath = 'TestDrive:\VhdExists.vhdx' -# } -# } -# @{ -# TestName = 'Vhd does not exist, Source File exists, Destination Path does not exist' -# FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\FileExists.txt' -# DestinationPath = 'DoesNotExist\' -# Type = 'File' -# Ensure = 'Present' -# } -# VhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' -# ExpectedResult = @{ -# FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# DestinationPath = 'TestDrive:\VhdDoesNotExist.vhdx' -# Ensure = 'Absent' -# } -# VhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' -# } -# } -# @{ -# TestName = 'Vhd does not exist, Source File does not exist, Destination Path does not exist' -# FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\DoesNotExist.txt' -# DestinationPath = 'DoesNotExist\' -# Type = 'File' -# Ensure = 'Present' -# } -# VhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' -# ExpectedResult = @{ -# FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# DestinationPath = 'TestDrive:\VhdDoesNotExist.vhdx' -# Ensure = 'Absent' -# } -# VhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' -# } -# } -# ) -# #endRegion - -# It 'Should correctly return state when: ' -TestCases $testCases_Get { -# param( -# $FileDirectoryProperties, -# $VhdPath, -# $ExpectedResult -# ) - -# $result = Get-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectoryProperties - -# $result['FileDirectory'].CimInstanceProperties.Value | -# Should -Be $ExpectedResult['FileDirectory'].CimInstanceProperties.Value - -# $result['VhdPath'] | -# Should -Be $ExpectedResult['VhdPath'] -# } -# } - -# Describe "DSC_VhdFileDirectory\Test-TargetResource" -Tag 'Test' { - -# BeforeAll { -# New-TestDriveLayout -DriveLetter $script:vhdDriveLetter -# } - -# AfterAll { -# Remove-PSDrive $script:vhdDriveLetter -ErrorAction SilentlyContinue -# } - -# Context 'When the system is in the desired state' { - -# $testCases_Test_InDesiredState = @( -# @{ -# TestName = 'VhdPath exists, Destination File exists, DestinationPath includes filename' -# VhdPath = 'TestDrive:\VhdExists.vhdx' -# FileDirectory = ( -# New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\FileExists.txt' -# DestinationPath = '\DestinationDirectoryExists\FileExists.txt' -# Ensure = 'Present' -# } -# ) -# } -# @{ -# TestName = 'VhdPath exists, Destination File exists, "Archive" attribute specified and set on file' -# VhdPath = 'TestDrive:\VhdExists.vhdx' -# FileDirectory = ( -# New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\FileExists.txt' -# DestinationPath = '\DestinationDirectoryExists\FileExists.txt' -# Attributes = 'Archive' -# Ensure = 'Present' -# } -# ) -# } -# @{ -# TestName = 'VhdPath exists, Destination File exists, DestinationPath does not include filename' -# VhdPath = 'TestDrive:\VhdExists.vhdx' -# FileDirectory = ( -# New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\FileExists.txt' -# DestinationPath = '\DestinationDirectoryExists' -# Ensure = 'Present' -# } -# ) -# } -# @{ -# TestName = 'Source is Directory, exists at destination' -# VhdPath = 'TestDrive:\VhdExists.vhdx' -# FileDirectory = ( -# New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\SourceDirectoryExists' -# DestinationPath = '\DestinationDirectoryExists' -# Ensure = 'Present' -# } -# ) -# } -# ) - -# It 'Should return [$true] when ' -TestCases $testCases_Test_InDesiredState { -# param ( -# $VhdPath, -# $FileDirectory -# ) - -# $result = Test-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectory -# $result | Should -Be $true -# } -# } - -# Context 'When the system is not in the desired state' { -# $testCases_Test_NotInDesiredState = @( -# @{ -# TestName = 'VhdPath exists, Destination File does not exist, DestinationPath includes Filename' -# VhdPath = 'TestDrive:\VhdExists.vhdx' -# FileDirectory = ( -# New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\FileExists.txt' -# DestinationPath = '\DestinationDirectoryExists\DoesNotExist.txt' -# Ensure = 'Present' -# } -# ) -# } -# @{ -# TestName = 'VhdPath exists, Destination File does not exist, DestinationPath does not include Filename' -# VhdPath = 'TestDrive:\VhdExists.vhdx' -# FileDirectory = ( -# New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\FileExists3.txt' -# DestinationPath = '\DestinationDirectoryExists' -# Ensure = 'Present' -# } -# ) -# } -# @{ -# TestName = 'Destination File exists, but "Ensure" is set to "Absent"' -# VhdPath = 'TestDrive:\VhdExists.vhdx' -# FileDirectory = ( -# New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\FileExists.txt' -# DestinationPath = '\DestinationDirectoryExists\FileExists.txt' -# Ensure = 'Absent' -# } -# ) -# } -# @{ -# TestName = 'Destination File exists, "Archive" attribute specified but not set on file' -# VhdPath = 'TestDrive:\VhdExists.vhdx' -# FileDirectory = ( -# New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\FileExists2.txt' -# DestinationPath = '\DestinationDirectoryExists\FileExists2.txt' -# Attributes = 'Archive' -# Ensure = 'Present' -# } -# ) -# } -# ) - -# It 'Should return [$false] when ' -TestCases $testCases_Test_NotInDesiredState { -# param ( -# $VhdPath, -# $FileDirectory -# ) - -# $result = Test-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectory -# $result | Should -Be $false -# } - -# It 'Should throw error when VhdPath does not exist' { -# $vhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' -# $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\FileExists.txt' -# DestinationPath = '\DestinationDirectoryExists\DoesNotExist.txt' -# Ensure = 'Present' -# } -# { Test-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory } | -# Should -Throw "VHD does not exist in the specified path $vhdPath" -# } -# } -# } - -# Describe "DSC_VhdFileDirectory\Set-TargetResource" -Tag 'Set' { -# BeforeAll { -# New-TestDriveLayout -DriveLetter $script:vhdDriveLetter -# } - -# AfterAll { -# Remove-PSDrive $script:vhdDriveLetter -ErrorAction SilentlyContinue -# } - -# Context 'When the system is in the desired state' { -# $testCases_Set_InDesiredState = @( -# @{ -# TestName = 'not throw' -# VhdPath = 'TestDrive:\VhdExists.vhdx' -# FileDirectory = ( -# New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\FileExists.txt' -# DestinationPath = '\DestinationDirectoryExists\FileExists.txt' -# Ensure = 'Present' -# } -# ) -# ExpectedResult = $null -# } -# ) - -# It 'Should ' -TestCases $testCases_Set_InDesiredState { -# param ( -# $VhdPath, -# $FileDirectory, -# $ExpectedResult -# ) - -# { Set-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectory } | Should -Not -throw -# } -# } - -# Context 'When the system is not in the desired state' { - -# It 'Should copy the source file to DestinationPath' { -# $vhdPath = 'TestDrive:\VhdExists.vhdx' -# $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\FileExists.txt' -# DestinationPath = '\DestinationDirectoryExists\FileDoesNotExist.txt' -# Ensure = 'Present' -# } - -# Set-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectory - -# (Get-FileHash TestDrive:\FileExists.txt).Hash | -# Should -Be (Get-FileHash TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileDoesNotExist.txt).hash -# } - -# It 'Should Insert content into file when "Content" is specified' { -# $vhdPath = 'TestDrive:\VhdExists.vhdx' -# $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# Content = 'This is some text' -# DestinationPath = '\DestinationDirectoryExists\FileDoesNotExist2.txt' -# Ensure = 'Present' -# } - -# Set-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory - -# Get-Content TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileDoesNotExist2.txt | -# Should -Be 'This is some text' -# } - -# It 'Should set "hidden" attribute when specified for nonexistent file' { -# $vhdPath = 'TestDrive:\VhdExists.vhdx' -# $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\FileExists.txt' -# DestinationPath = '\DestinationDirectoryExists\FileDoesNotExist3.txt' -# Ensure = 'Present' -# Attributes = 'Hidden' -# } - -# Set-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory - -# (Get-Item TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileDoesNotExist3.txt -Force).Attributes | -# Should -Be 'Hidden' -# } - -# It 'Should remove the file when "Ensure" is set to "Absent"' { -# $vhdPath = 'TestDrive:\VhdExists.vhdx' -# $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\FileExists.txt' -# DestinationPath = '\DestinationDirectoryExists\FileExists.txt' -# Ensure = 'Absent' -# } - -# Set-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory - -# Test-Path TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileExists.txt | -# Should -Be $false -# } - -# It 'Should throw error when VhdPath does not exist' { -# $vhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' -# $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ -# SourcePath = 'TestDrive:\FileExists.txt' -# DestinationPath = '\DestinationDirectoryDoesNotExist\FileDoesNotExist.txt' -# Ensure = 'Present' -# } - -# { Set-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory } | -# Should -Throw "Specified destination path $vhdPath does not exist!" -# } -# } -# } -# } -# } -# finally -# { -# Invoke-TestCleanup -# } +$script:dscModuleName = 'HyperVDsc' +$script:dscResourceName = 'DSC_VhdFileDirectory' + +function Invoke-TestSetup +{ + try + { + Import-Module -Name DscResource.Test -Force -ErrorAction 'Stop' + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -Tasks build" first.' + } + + $script:testEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:dscModuleName ` + -DSCResourceName $script:dscResourceName ` + -ResourceType 'Mof' ` + -TestType 'Unit' + + # Import the stub functions. + Import-Module -Name "$PSScriptRoot/Stubs/Hyper-V.stubs.psm1" -Force +} + +function Invoke-TestCleanup +{ + Restore-TestEnvironment -TestEnvironment $script:testEnvironment +} + +Invoke-TestSetup + +try +{ + InModuleScope $script:dscResourceName { + + #region Functions, Variables and Mocks + function Get-FreeDriveLetter + { + [CmdletBinding()] + param() + + $upperCaseChars = 67..90 | ForEach-Object { [char]$_ } + $driveLettersInUse = Get-PsDrive | Where-Object -FilterScript { + $upperCaseChars -contains $_.name + } | Select-Object -ExpandProperty Name + + foreach ($char in $upperCaseChars) + { + if ($driveLettersInUse -notcontains $char) + { + Write-Verbose "Selecting $char to use as VhdDriveLetter" + + return $char + break + } + } +} + +function New-TestDriveLayout +{ + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = "Medium")] + param( + [Parameter()] + [System.String] + $DriveLetter + ) + + # Source file structure + New-item -Path TestDrive:\VhdExists.vhdx + 'TestFile1' | Out-File TestDrive:\FileExists.txt + 'TestFile2' | Out-File TestDrive:\FileExists2.txt + 'TestFile3' | Out-File TestDrive:\FileExists3.txt + New-Item -Path TestDrive:\SourceDirectoryExists -ItemType Directory + New-Item -Path TestDrive:\SourceDirectoryExists2 -ItemType Directory + 'Some Text' | Out-File TestDrive:\SourceDirectoryExists\File1.txt + 'Some More Text' | Out-File TestDrive:\SourceDirectoryExists2\File2.txt + + # VhdRoot structure + New-Item -Path TestDrive:\MockVhdRoot -ItemType Directory + New-Item -Path TestDrive:\MockVhdRoot\DestinationDirectoryExists -ItemType Directory + Copy-Item -Path TestDrive:\FileExists.txt -Destination TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileExists.txt + Copy-Item -Path TestDrive:\FileExists2.txt -Destination TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileExists2.txt + Copy-Item -Path TestDrive:\SourceDirectoryExists TestDrive:\DestinationDirectoryExists\SourceDirectory -Recurse + (Get-Item TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileExists2.txt).Attributes = '' + + # ShouldProcess supported by New-PsDrive + New-PSDrive -PSProvider FileSystem -Name $DriveLetter -Root TestDrive:\MockVhdRoot -scope 1 +} + +$script:vhdDriveLetter = Get-FreeDriveLetter + +# function Mount-Vhd {} +# function Dismount-Vhd {} +# function Get-Disk {} +# function Get-Partition {} +# function Get-Volume {} + +$script:dscFileDirClassName = 'DSC_FileDirectoryConfiguration' +$script:dscNamespace = 'root/microsoft/windows/desiredstateconfiguration' + +Mock -CommandName Mount-Vhd { [PSCustomObject] @{ Path = 'TestDrive:\VhdExists.vhdx' } } + +Mock -CommandName Dismount-Vhd { } + +Mock -CommandName Get-Disk { + New-CimInstance -ClassName MSFT_Disk -Namespace root/Microsoft/Windows/Storage -ClientOnly +} + +Mock -CommandName Get-Partition { + New-CimInstance -ClassName DSC_Partitions -Namespace ROOT/Microsoft/Windows/Storage -ClientOnly | + Add-Member -MemberType NoteProperty -Name Type -Value 'Mocked' -Force -PassThru | + Add-Member -MemberType NoteProperty -Name DriveLetter -Value $script:vhdDriveLetter -PassThru +} + +Mock -CommandName Get-Volume { + New-CimInstance -ClassName DSC_Volumes -Namespace ROOT/Microsoft/Windows/Storage -ClientOnly | + Add-Member -MemberType NoteProperty -Name DriveLetter -Value $script:vhdDriveLetter -PassThru +} + +Mock -CommandName Get-Module { + $true +} -ParameterFilter { $Name -and $Name -eq "Hyper-V" } + +#endregion + +Describe 'DSC_VhdFileDirectory\Get-TargetResource' -Tag 'Get' { + + BeforeAll { + New-TestDriveLayout -DriveLetter $script:vhdDriveLetter + } + + AfterAll { + Remove-PSDrive $script:vhdDriveLetter -ErrorAction SilentlyContinue + } + + It 'Should return a [System.Collections.Hashtable] object type' { + $fdProperties = @{ + SourcePath = 'TestDrive:\FileExists.txt' + DestinationPath = '\DestinationDirectoryExists\' + Type = 'File' + Ensure = 'Present' + } + + $fileDirectory = New-CimInstance -Property $fdProperties -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly + $result = Get-TargetResource -VhdPath TestDrive:\VhdExists.vhdx -FileDirectory $fileDirectory + + $result -is [System.Collections.Hashtable] | + Should -Be $true + } + + #region Testcases for Get-TargetResource + $testCases_Get = @( + @{ + TestName = 'VhdFile exists, Source File exists, Destination File exists' + FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\FileExists.txt' + DestinationPath = 'DestinationDirectoryExists\FileExists.txt' + Type = 'File' + Ensure = 'Present' + } + VhdPath = 'TestDrive:\VhdExists.vhdx' + ExpectedResult = @{ + FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + DestinationPath = $script:vhdDriveLetter + ':\DestinationDirectoryExists\FileExists.txt' + Ensure = 'Present' + } + VhdPath = 'TestDrive:\VhdExists.vhdx' + } + } + @{ + TestName = 'VhdFile exists, Source File exists, Destination File does not exist' + FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\FileExists.txt' + DestinationPath = 'DestinationDirectoryExists\DoesNotExist.txt' + Type = 'File' + Ensure = 'Present' + } + VhdPath = 'TestDrive:\VhdExists.vhdx' + ExpectedResult = @{ + FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + DestinationPath = $script:vhdDriveLetter + ':\DestinationDirectoryExists\DoesNotExist.txt' + Ensure = 'Absent' + } + VhdPath = 'TestDrive:\VhdExists.vhdx' + } + } + @{ + TestName = 'VhdFile exists, Source File does not exist, Destination File exists' + FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\DoesNotExist.txt' + DestinationPath = 'DestinationDirectoryExists\FileExists.txt' + Type = 'File' + Ensure = 'Present' + } + VhdPath = 'TestDrive:\VhdExists.vhdx' + ExpectedResult = @{ + FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + DestinationPath = $script:vhdDriveLetter + ':\DestinationDirectoryExists\FileExists.txt' + Ensure = 'Present' + } + VhdPath = 'TestDrive:\VhdExists.vhdx' + } + } + @{ + TestName = 'VhdFile exists, Source File does not exist, Destination File does not exist' + FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\DoesNotExist.txt' + DestinationPath = 'DestinationDirectoryExists\DoesNotExist.txt' + Type = 'File' + Ensure = 'Present' + } + VhdPath = 'TestDrive:\VhdExists.vhdx' + ExpectedResult = @{ + FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + DestinationPath = $script:vhdDriveLetter + ':\DestinationDirectoryExists\DoesNotExist.txt' + Ensure = 'Absent' + } + VhdPath = 'TestDrive:\VhdExists.vhdx' + } + } + @{ + TestName = 'Vhd does not exist, Source File exists, Destination Path does not exist' + FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\FileExists.txt' + DestinationPath = 'DoesNotExist\' + Type = 'File' + Ensure = 'Present' + } + VhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' + ExpectedResult = @{ + FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + DestinationPath = 'TestDrive:\VhdDoesNotExist.vhdx' + Ensure = 'Absent' + } + VhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' + } + } + @{ + TestName = 'Vhd does not exist, Source File does not exist, Destination Path does not exist' + FileDirectoryProperties = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\DoesNotExist.txt' + DestinationPath = 'DoesNotExist\' + Type = 'File' + Ensure = 'Present' + } + VhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' + ExpectedResult = @{ + FileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + DestinationPath = 'TestDrive:\VhdDoesNotExist.vhdx' + Ensure = 'Absent' + } + VhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' + } + } + ) + #endRegion + + It 'Should correctly return state when: ' -TestCases $testCases_Get { + param( + $FileDirectoryProperties, + $VhdPath, + $ExpectedResult + ) + + $result = Get-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectoryProperties + + $result['FileDirectory'].CimInstanceProperties.Value | + Should -Be $ExpectedResult['FileDirectory'].CimInstanceProperties.Value + + $result['VhdPath'] | + Should -Be $ExpectedResult['VhdPath'] + } +} + +Describe "DSC_VhdFileDirectory\Test-TargetResource" -Tag 'Test' { + + BeforeAll { + New-TestDriveLayout -DriveLetter $script:vhdDriveLetter + } + + AfterAll { + Remove-PSDrive $script:vhdDriveLetter -ErrorAction SilentlyContinue + } + + Context 'When the system is in the desired state' { + + $testCases_Test_InDesiredState = @( + @{ + TestName = 'VhdPath exists, Destination File exists, DestinationPath includes filename' + VhdPath = 'TestDrive:\VhdExists.vhdx' + FileDirectory = ( + New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\FileExists.txt' + DestinationPath = '\DestinationDirectoryExists\FileExists.txt' + Ensure = 'Present' + } + ) + } + @{ + TestName = 'VhdPath exists, Destination File exists, "Archive" attribute specified and set on file' + VhdPath = 'TestDrive:\VhdExists.vhdx' + FileDirectory = ( + New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\FileExists.txt' + DestinationPath = '\DestinationDirectoryExists\FileExists.txt' + Attributes = 'Archive' + Ensure = 'Present' + } + ) + } + @{ + TestName = 'VhdPath exists, Destination File exists, DestinationPath does not include filename' + VhdPath = 'TestDrive:\VhdExists.vhdx' + FileDirectory = ( + New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\FileExists.txt' + DestinationPath = '\DestinationDirectoryExists' + Ensure = 'Present' + } + ) + } + @{ + TestName = 'Source is Directory, exists at destination' + VhdPath = 'TestDrive:\VhdExists.vhdx' + FileDirectory = ( + New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\SourceDirectoryExists' + DestinationPath = '\DestinationDirectoryExists' + Ensure = 'Present' + } + ) + } + ) + + It 'Should return [$true] when ' -TestCases $testCases_Test_InDesiredState { + param ( + $VhdPath, + $FileDirectory + ) + + $result = Test-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectory + $result | Should -Be $true + } + } + + Context 'When the system is not in the desired state' { + $testCases_Test_NotInDesiredState = @( + @{ + TestName = 'VhdPath exists, Destination File does not exist, DestinationPath includes Filename' + VhdPath = 'TestDrive:\VhdExists.vhdx' + FileDirectory = ( + New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\FileExists.txt' + DestinationPath = '\DestinationDirectoryExists\DoesNotExist.txt' + Ensure = 'Present' + } + ) + } + @{ + TestName = 'VhdPath exists, Destination File does not exist, DestinationPath does not include Filename' + VhdPath = 'TestDrive:\VhdExists.vhdx' + FileDirectory = ( + New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\FileExists3.txt' + DestinationPath = '\DestinationDirectoryExists' + Ensure = 'Present' + } + ) + } + @{ + TestName = 'Destination File exists, but "Ensure" is set to "Absent"' + VhdPath = 'TestDrive:\VhdExists.vhdx' + FileDirectory = ( + New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\FileExists.txt' + DestinationPath = '\DestinationDirectoryExists\FileExists.txt' + Ensure = 'Absent' + } + ) + } + @{ + TestName = 'Destination File exists, "Archive" attribute specified but not set on file' + VhdPath = 'TestDrive:\VhdExists.vhdx' + FileDirectory = ( + New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\FileExists2.txt' + DestinationPath = '\DestinationDirectoryExists\FileExists2.txt' + Attributes = 'Archive' + Ensure = 'Present' + } + ) + } + ) + + It 'Should return [$false] when ' -TestCases $testCases_Test_NotInDesiredState { + param ( + $VhdPath, + $FileDirectory + ) + + $result = Test-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectory + $result | Should -Be $false + } + + It 'Should throw error when VhdPath does not exist' { + $vhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' + $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\FileExists.txt' + DestinationPath = '\DestinationDirectoryExists\DoesNotExist.txt' + Ensure = 'Present' + } + { Test-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory } | + Should -Throw "VHD does not exist in the specified path $vhdPath" + } + } +} + +Describe "DSC_VhdFileDirectory\Set-TargetResource" -Tag 'Set' { + BeforeAll { + New-TestDriveLayout -DriveLetter $script:vhdDriveLetter + } + + AfterAll { + Remove-PSDrive $script:vhdDriveLetter -ErrorAction SilentlyContinue + } + + Context 'When the system is in the desired state' { + $testCases_Set_InDesiredState = @( + @{ + TestName = 'not throw' + VhdPath = 'TestDrive:\VhdExists.vhdx' + FileDirectory = ( + New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\FileExists.txt' + DestinationPath = '\DestinationDirectoryExists\FileExists.txt' + Ensure = 'Present' + } + ) + ExpectedResult = $null + } + ) + + It 'Should ' -TestCases $testCases_Set_InDesiredState { + param ( + $VhdPath, + $FileDirectory, + $ExpectedResult + ) + + { Set-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectory } | Should -Not -throw + } + } + + Context 'When the system is not in the desired state' { + + It 'Should copy the source file to DestinationPath' { + $vhdPath = 'TestDrive:\VhdExists.vhdx' + $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\FileExists.txt' + DestinationPath = '\DestinationDirectoryExists\FileDoesNotExist.txt' + Ensure = 'Present' + } + + Set-TargetResource -VhdPath $VhdPath -FileDirectory $FileDirectory + + (Get-FileHash TestDrive:\FileExists.txt).Hash | + Should -Be (Get-FileHash TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileDoesNotExist.txt).hash + } + + It 'Should Insert content into file when "Content" is specified' { + $vhdPath = 'TestDrive:\VhdExists.vhdx' + $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + Content = 'This is some text' + DestinationPath = '\DestinationDirectoryExists\FileDoesNotExist2.txt' + Ensure = 'Present' + } + + Set-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory + + Get-Content TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileDoesNotExist2.txt | + Should -Be 'This is some text' + } + + It 'Should set "hidden" attribute when specified for nonexistent file' { + $vhdPath = 'TestDrive:\VhdExists.vhdx' + $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\FileExists.txt' + DestinationPath = '\DestinationDirectoryExists\FileDoesNotExist3.txt' + Ensure = 'Present' + Attributes = 'Hidden' + } + + Set-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory + + (Get-Item TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileDoesNotExist3.txt -Force).Attributes | + Should -Be 'Hidden' + } + + It 'Should remove the file when "Ensure" is set to "Absent"' { + $vhdPath = 'TestDrive:\VhdExists.vhdx' + $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\FileExists.txt' + DestinationPath = '\DestinationDirectoryExists\FileExists.txt' + Ensure = 'Absent' + } + + Set-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory + + Test-Path TestDrive:\MockVhdRoot\DestinationDirectoryExists\FileExists.txt | + Should -Be $false + } + + It 'Should throw error when VhdPath does not exist' { + $vhdPath = 'TestDrive:\VhdDoesNotExist.vhdx' + $fileDirectory = New-CimInstance -ClassName $script:dscFileDirClassName -Namespace $script:dscNamespace -ClientOnly -Property @{ + SourcePath = 'TestDrive:\FileExists.txt' + DestinationPath = '\DestinationDirectoryDoesNotExist\FileDoesNotExist.txt' + Ensure = 'Present' + } + + { Set-TargetResource -VhdPath $vhdPath -FileDirectory $fileDirectory } | + Should -Throw "Specified destination path $vhdPath does not exist!" + } + } +} +} +} +finally +{ + Invoke-TestCleanup +} From 00b37dfdd5444d24be0dacb5f5d15a9d8290e277 Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Fri, 31 Jan 2025 16:47:29 +0000 Subject: [PATCH 4/6] Use correct test file names --- .../Private/Wait-VMIPAddress.Tests.ps1 | 4 +- .../Public/ConvertFrom-TimeSpan.Tests.ps1 | 56 ++++++++ .../Public/ConvertFrom-TimeSpan.ps1 | 51 ------- .../Public/ConvertTo-TimeSpan.Tests.ps1 | 56 ++++++++ .../Public/ConvertTo-TimeSpan.ps1 | 51 ------- .../Public/Get-VMHyperV.Tests.ps1 | 73 ++++++++++ .../HyperVDsc.Common/Public/Get-VMHyperV.ps1 | 68 --------- .../Public/Set-VMProperty.Tests.ps1 | 82 +++++++++++ .../Public/Set-VMProperty.ps1 | 77 ----------- .../Public/Set-VMState.Tests.ps1 | 130 ++++++++++++++++++ .../HyperVDsc.Common/Public/Set-VMState.ps1 | 125 ----------------- 11 files changed, 398 insertions(+), 375 deletions(-) create mode 100644 tests/Unit/HyperVDsc.Common/Public/ConvertFrom-TimeSpan.Tests.ps1 delete mode 100644 tests/Unit/HyperVDsc.Common/Public/ConvertFrom-TimeSpan.ps1 create mode 100644 tests/Unit/HyperVDsc.Common/Public/ConvertTo-TimeSpan.Tests.ps1 delete mode 100644 tests/Unit/HyperVDsc.Common/Public/ConvertTo-TimeSpan.ps1 create mode 100644 tests/Unit/HyperVDsc.Common/Public/Get-VMHyperV.Tests.ps1 delete mode 100644 tests/Unit/HyperVDsc.Common/Public/Get-VMHyperV.ps1 create mode 100644 tests/Unit/HyperVDsc.Common/Public/Set-VMProperty.Tests.ps1 delete mode 100644 tests/Unit/HyperVDsc.Common/Public/Set-VMProperty.ps1 create mode 100644 tests/Unit/HyperVDsc.Common/Public/Set-VMState.Tests.ps1 delete mode 100644 tests/Unit/HyperVDsc.Common/Public/Set-VMState.ps1 diff --git a/tests/Unit/HyperVDsc.Common/Private/Wait-VMIPAddress.Tests.ps1 b/tests/Unit/HyperVDsc.Common/Private/Wait-VMIPAddress.Tests.ps1 index bf7a354..b29ae07 100644 --- a/tests/Unit/HyperVDsc.Common/Private/Wait-VMIPAddress.Tests.ps1 +++ b/tests/Unit/HyperVDsc.Common/Private/Wait-VMIPAddress.Tests.ps1 @@ -26,9 +26,7 @@ Import-Module $script:subModuleFile -Force -ErrorAction 'Stop' #Get-Module -Name 'Hyper-V' -All | Remove-Module -Force Import-Module -Name "$PSScriptRoot/../../Stubs/Hyper-V.stubs.psm1" -Force -DisableNameChecking -Write-Warning ('ParentModule = {0}' -f $script:parentModule) - -InModuleScope $script:parentModule { +InModuleScope $script:subModuleName { Describe 'Private\Wait-VMIPAddress' { Context 'When VM network adapter reports 2 IP addresses' { BeforeAll { diff --git a/tests/Unit/HyperVDsc.Common/Public/ConvertFrom-TimeSpan.Tests.ps1 b/tests/Unit/HyperVDsc.Common/Public/ConvertFrom-TimeSpan.Tests.ps1 new file mode 100644 index 0000000..2254053 --- /dev/null +++ b/tests/Unit/HyperVDsc.Common/Public/ConvertFrom-TimeSpan.Tests.ps1 @@ -0,0 +1,56 @@ +#region HEADER +$script:projectPath = "$PSScriptRoot\..\..\..\.." | Convert-Path +$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and + $(try + { + Test-ModuleManifest -Path $_.FullName -ErrorAction Stop + } + catch + { + $false + }) + }).BaseName + +$script:parentModule = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 +$script:subModulesFolder = Join-Path -Path $script:parentModule.ModuleBase -ChildPath 'Modules' +Remove-Module -Name $script:parentModule -Force -ErrorAction 'SilentlyContinue' + +$script:subModuleName = ('{0}.Common' -f $script:projectName) +$script:subModuleFile = Join-Path -Path $script:subModulesFolder -ChildPath "$($script:subModuleName)" + +Import-Module $script:subModuleFile -Force -ErrorAction 'Stop' +#endregion HEADER + +# Import the stub functions. +#Get-Module -Name 'Hyper-V' -All | Remove-Module -Force +Import-Module -Name "$PSScriptRoot/../../Stubs/Hyper-V.stubs.psm1" -Force -DisableNameChecking + +InModuleScope $script:subModuleName { + Describe 'Public\ConvertFrom-TimeSpan' { + It 'Should convert a "System.TimeSpan" of 1 minute to 60 seconds' { + $testTimeSpan = New-TimeSpan -Minutes 1 + + $result = ConvertFrom-TimeSpan -TimeSpan $testTimeSpan -TimeSpanType Seconds + + $result | Should -Be 60 + } + + It 'Should convert a "System.TimeSpan" of 1 hour to 60 minutes' { + $testTimeSpan = New-TimeSpan -Hours 1 + + $result = ConvertFrom-TimeSpan -TimeSpan $testTimeSpan -TimeSpanType Minutes + + $result | Should -Be 60 + } + + It 'Should convert a "System.TimeSpan" of 2 dayes to 48 hours' { + $testTimeSpan = New-TimeSpan -Days 2 + + $result = ConvertFrom-TimeSpan -TimeSpan $testTimeSpan -TimeSpanType Hours + + $result | Should -Be 48 + } + + } +} diff --git a/tests/Unit/HyperVDsc.Common/Public/ConvertFrom-TimeSpan.ps1 b/tests/Unit/HyperVDsc.Common/Public/ConvertFrom-TimeSpan.ps1 deleted file mode 100644 index f9694c0..0000000 --- a/tests/Unit/HyperVDsc.Common/Public/ConvertFrom-TimeSpan.ps1 +++ /dev/null @@ -1,51 +0,0 @@ -# #region HEADER -# $script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path -# $script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { -# ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and -# $(try -# { -# Test-ModuleManifest -Path $_.FullName -ErrorAction Stop -# } -# catch -# { -# $false -# }) -# }).BaseName - -# $script:parentModule = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 - -# Import-Module $script:parentModule -Force -ErrorAction 'Stop' -# #endregion HEADER - -# # Import the stub functions. -# #Get-Module -Name 'Hyper-V' -All | Remove-Module -Force -# Import-Module -Name "$PSScriptRoot/../../Stubs/Hyper-V.stubs.psm1" -Force - -# InModuleScope $script:parentModule { -# Describe 'Public\ConvertFrom-TimeSpan' { -# It 'Should convert a "System.TimeSpan" of 1 minute to 60 seconds' { -# $testTimeSpan = New-TimeSpan -Minutes 1 - -# $result = ConvertFrom-TimeSpan -TimeSpan $testTimeSpan -TimeSpanType Seconds - -# $result | Should -Be 60 -# } - -# It 'Should convert a "System.TimeSpan" of 1 hour to 60 minutes' { -# $testTimeSpan = New-TimeSpan -Hours 1 - -# $result = ConvertFrom-TimeSpan -TimeSpan $testTimeSpan -TimeSpanType Minutes - -# $result | Should -Be 60 -# } - -# It 'Should convert a "System.TimeSpan" of 2 dayes to 48 hours' { -# $testTimeSpan = New-TimeSpan -Days 2 - -# $result = ConvertFrom-TimeSpan -TimeSpan $testTimeSpan -TimeSpanType Hours - -# $result | Should -Be 48 -# } - -# } -# } diff --git a/tests/Unit/HyperVDsc.Common/Public/ConvertTo-TimeSpan.Tests.ps1 b/tests/Unit/HyperVDsc.Common/Public/ConvertTo-TimeSpan.Tests.ps1 new file mode 100644 index 0000000..3369a32 --- /dev/null +++ b/tests/Unit/HyperVDsc.Common/Public/ConvertTo-TimeSpan.Tests.ps1 @@ -0,0 +1,56 @@ +#region HEADER +$script:projectPath = "$PSScriptRoot\..\..\..\.." | Convert-Path +$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and + $(try + { + Test-ModuleManifest -Path $_.FullName -ErrorAction Stop + } + catch + { + $false + }) + }).BaseName + +$script:parentModule = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 +$script:subModulesFolder = Join-Path -Path $script:parentModule.ModuleBase -ChildPath 'Modules' +Remove-Module -Name $script:parentModule -Force -ErrorAction 'SilentlyContinue' + +$script:subModuleName = ('{0}.Common' -f $script:projectName) +$script:subModuleFile = Join-Path -Path $script:subModulesFolder -ChildPath "$($script:subModuleName)" + +Import-Module $script:subModuleFile -Force -ErrorAction 'Stop' +#endregion HEADER + +# Import the stub functions. +#Get-Module -Name 'Hyper-V' -All | Remove-Module -Force +Import-Module -Name "$PSScriptRoot/../../Stubs/Hyper-V.stubs.psm1" -Force -DisableNameChecking + +InModuleScope $script:subModuleName { + Describe 'Public\ConvertTo-TimeSpan' { + It 'Should convert 60 seconds to "System.TimeSpan" of 1 minute' { + $testSeconds = 60 + + $result = ConvertTo-TimeSpan -TimeInterval $testSeconds -TimeIntervalType Seconds + + $result.TotalMinutes | Should -Be 1 + } + + It 'Should convert 60 minutes to "System.TimeSpan" of 60 minutes' { + $testMinutes = 60 + + $result = ConvertTo-TimeSpan -TimeInterval $testMinutes -TimeIntervalType Minutes + + $result.TotalHours | Should -Be 1 + } + + It 'Should convert 48 hours to "System.TimeSpan" of 2 days' { + $testHours = 48 + + $result = ConvertTo-TimeSpan -TimeInterval $testHours -TimeIntervalType Hours + + $result.TotalDays | Should -Be 2 + } + + } +} diff --git a/tests/Unit/HyperVDsc.Common/Public/ConvertTo-TimeSpan.ps1 b/tests/Unit/HyperVDsc.Common/Public/ConvertTo-TimeSpan.ps1 deleted file mode 100644 index 0c8b87c..0000000 --- a/tests/Unit/HyperVDsc.Common/Public/ConvertTo-TimeSpan.ps1 +++ /dev/null @@ -1,51 +0,0 @@ -# #region HEADER -# $script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path -# $script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { -# ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and -# $(try -# { -# Test-ModuleManifest -Path $_.FullName -ErrorAction Stop -# } -# catch -# { -# $false -# }) -# }).BaseName - -# $script:parentModule = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 - -# Import-Module $script:parentModule -Force -ErrorAction 'Stop' -# #endregion HEADER - -# # Import the stub functions. -# #Get-Module -Name 'Hyper-V' -All | Remove-Module -Force -# Import-Module -Name "$PSScriptRoot/../../Stubs/Hyper-V.stubs.psm1" -Force - -# InModuleScope $script:parentModule { -# Describe 'Public\ConvertTo-TimeSpan' { -# It 'Should convert 60 seconds to "System.TimeSpan" of 1 minute' { -# $testSeconds = 60 - -# $result = ConvertTo-TimeSpan -TimeInterval $testSeconds -TimeIntervalType Seconds - -# $result.TotalMinutes | Should -Be 1 -# } - -# It 'Should convert 60 minutes to "System.TimeSpan" of 60 minutes' { -# $testMinutes = 60 - -# $result = ConvertTo-TimeSpan -TimeInterval $testMinutes -TimeIntervalType Minutes - -# $result.TotalHours | Should -Be 1 -# } - -# It 'Should convert 48 hours to "System.TimeSpan" of 2 days' { -# $testHours = 48 - -# $result = ConvertTo-TimeSpan -TimeInterval $testHours -TimeIntervalType Hours - -# $result.TotalDays | Should -Be 2 -# } - -# } -# } diff --git a/tests/Unit/HyperVDsc.Common/Public/Get-VMHyperV.Tests.ps1 b/tests/Unit/HyperVDsc.Common/Public/Get-VMHyperV.Tests.ps1 new file mode 100644 index 0000000..ffd1fba --- /dev/null +++ b/tests/Unit/HyperVDsc.Common/Public/Get-VMHyperV.Tests.ps1 @@ -0,0 +1,73 @@ +#region HEADER +$script:projectPath = "$PSScriptRoot\..\..\..\.." | Convert-Path +$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and + $(try + { + Test-ModuleManifest -Path $_.FullName -ErrorAction Stop + } + catch + { + $false + }) + }).BaseName + +$script:parentModule = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 +$script:subModulesFolder = Join-Path -Path $script:parentModule.ModuleBase -ChildPath 'Modules' +Remove-Module -Name $script:parentModule -Force -ErrorAction 'SilentlyContinue' + +$script:subModuleName = ('{0}.Common' -f $script:projectName) +$script:subModuleFile = Join-Path -Path $script:subModulesFolder -ChildPath "$($script:subModuleName)" + +Import-Module $script:subModuleFile -Force -ErrorAction 'Stop' +#endregion HEADER + +# Import the stub functions. +#Get-Module -Name 'Hyper-V' -All | Remove-Module -Force +Import-Module -Name "$PSScriptRoot/../../Stubs/Hyper-V.stubs.psm1" -Force -DisableNameChecking + +InModuleScope $script:subModuleName { + Describe 'Public\Get-VMHyperV' { + BeforeAll { + $mockVMName = 'TestVM' + } + + # Guard mocks + It 'Should not throw when no VM is found' { + Mock -CommandName Get-VM + + $result = Get-VMHyperV -VMName $mockVMName + + $result | Should -BeNullOrEmpty + } + + It 'Should not throw when one VM is found' { + Mock -CommandName Get-VM -MockWith { + [PSCustomObject] @{ + Name = $VMName + } + } + + $result = Get-VMHyperV -VMName $mockVMName + + $result.Name | Should -Be $mockVMName + } + + It 'Should throw when more than one VM is found' { + Mock -CommandName Get-VM -MockWith { + @( + [PSCustomObject] @{ + Name = $VMName + }, + [PSCustomObject] @{ + Name = $VMName + } + ) + } + + { Get-VMHyperV -VMName $mockVMName } | Should -Throw ( + $script:localizedData.MoreThanOneVMExistsError -f $mockVMName + ) + } + } +} diff --git a/tests/Unit/HyperVDsc.Common/Public/Get-VMHyperV.ps1 b/tests/Unit/HyperVDsc.Common/Public/Get-VMHyperV.ps1 deleted file mode 100644 index 728a3d9..0000000 --- a/tests/Unit/HyperVDsc.Common/Public/Get-VMHyperV.ps1 +++ /dev/null @@ -1,68 +0,0 @@ -# #region HEADER -# $script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path -# $script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { -# ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and -# $(try -# { -# Test-ModuleManifest -Path $_.FullName -ErrorAction Stop -# } -# catch -# { -# $false -# }) -# }).BaseName - -# $script:parentModule = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 - -# Import-Module $script:parentModule -Force -ErrorAction 'Stop' -# #endregion HEADER - -# # Import the stub functions. -# #Get-Module -Name 'Hyper-V' -All | Remove-Module -Force -# Import-Module -Name "$PSScriptRoot/../Stubs/Hyper-V.stubs.psm1" -Force - -# InModuleScope $script:parentModule { -# Describe 'Public\Get-VMHyperV' { -# BeforeAll { -# $mockVMName = 'TestVM' -# } - -# # Guard mocks -# It 'Should not throw when no VM is found' { -# Mock -CommandName Get-VM - -# $result = Get-VMHyperV -VMName $mockVMName - -# $result | Should -BeNullOrEmpty -# } - -# It 'Should not throw when one VM is found' { -# Mock -CommandName Get-VM -MockWith { -# [PSCustomObject] @{ -# Name = $VMName -# } -# } - -# $result = Get-VMHyperV -VMName $mockVMName - -# $result.Name | Should -Be $mockVMName -# } - -# It 'Should throw when more than one VM is found' { -# Mock -CommandName Get-VM -MockWith { -# @( -# [PSCustomObject] @{ -# Name = $VMName -# }, -# [PSCustomObject] @{ -# Name = $VMName -# } -# ) -# } - -# { Get-VMHyperV -VMName $mockVMName } | Should -Throw ( -# $script:localizedData.MoreThanOneVMExistsError -f $mockVMName -# ) -# } -# } -# } diff --git a/tests/Unit/HyperVDsc.Common/Public/Set-VMProperty.Tests.ps1 b/tests/Unit/HyperVDsc.Common/Public/Set-VMProperty.Tests.ps1 new file mode 100644 index 0000000..d7d0270 --- /dev/null +++ b/tests/Unit/HyperVDsc.Common/Public/Set-VMProperty.Tests.ps1 @@ -0,0 +1,82 @@ +#region HEADER +$script:projectPath = "$PSScriptRoot\..\..\..\.." | Convert-Path +$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and + $(try + { + Test-ModuleManifest -Path $_.FullName -ErrorAction Stop + } + catch + { + $false + }) + }).BaseName + +$script:parentModule = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 +$script:subModulesFolder = Join-Path -Path $script:parentModule.ModuleBase -ChildPath 'Modules' +Remove-Module -Name $script:parentModule -Force -ErrorAction 'SilentlyContinue' + +$script:subModuleName = ('{0}.Common' -f $script:projectName) +$script:subModuleFile = Join-Path -Path $script:subModulesFolder -ChildPath "$($script:subModuleName)" + +Import-Module $script:subModuleFile -Force -ErrorAction 'Stop' +#endregion HEADER + +# Import the stub functions. +#Get-Module -Name 'Hyper-V' -All | Remove-Module -Force +Import-Module -Name "$PSScriptRoot/../../Stubs/Hyper-V.stubs.psm1" -Force -DisableNameChecking + +InModuleScope $script:subModuleName { + Describe 'Public\Set-VMProperty' { + It "Should throw if VM is running and 'RestartIfNeeded' is False" { + $mockVMName = 'Test' + + Mock -CommandName Get-VM -MockWith { + return @{ + State = 'Running' + } + } + + $setVMPropertyParams = @{ + VMName = $mockVMName + VMCommand = 'Set-VMProcessor' + ChangeProperty = @{ + ResourcePoolName = 'Dummy' + } + } + + { Set-VMProperty @setVMPropertyParams } | Should -Throw ( + $script:localizedData.CannotUpdatePropertiesOnlineError -f $mockVMName, 'Running' + ) + } + + It "Should stop and restart VM when running and 'RestartIfNeeded' is True" { + Mock -CommandName Stop-VM + Mock -CommandName Set-VMProcessor + Mock -CommandName Set-VMState + Mock -CommandName Get-VM -MockWith { + return @{ + State = 'Running' + } + } + + $setVMPropertyParams = @{ + VMName = 'Test' + VMCommand = 'Set-VMProcessor' + ChangeProperty = @{ + ResourcePoolName = 'Dummy' + } + RestartIfNeeded = $true + } + Set-VMProperty @setVMPropertyParams + + Assert-MockCalled -CommandName Set-VMState -ParameterFilter { + $State -eq 'Off' + } -Scope It + + Assert-MockCalled -CommandName Set-VMState -ParameterFilter { + $State -eq 'Running' + } -Scope It + } + } +} diff --git a/tests/Unit/HyperVDsc.Common/Public/Set-VMProperty.ps1 b/tests/Unit/HyperVDsc.Common/Public/Set-VMProperty.ps1 deleted file mode 100644 index efc987f..0000000 --- a/tests/Unit/HyperVDsc.Common/Public/Set-VMProperty.ps1 +++ /dev/null @@ -1,77 +0,0 @@ -# #region HEADER -# $script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path -# $script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { -# ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and -# $(try -# { -# Test-ModuleManifest -Path $_.FullName -ErrorAction Stop -# } -# catch -# { -# $false -# }) -# }).BaseName - -# $script:parentModule = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 - -# Import-Module $script:parentModule -Force -ErrorAction 'Stop' -# #endregion HEADER - -# # Import the stub functions. -# #Get-Module -Name 'Hyper-V' -All | Remove-Module -Force -# Import-Module -Name "$PSScriptRoot/../Stubs/Hyper-V.stubs.psm1" -Force - -# InModuleScope $script:parentModule { -# Describe 'Public\Set-VMProperty' { -# It "Should throw if VM is running and 'RestartIfNeeded' is False" { -# $mockVMName = 'Test' - -# Mock -CommandName Get-VM -MockWith { -# return @{ -# State = 'Running' -# } -# } - -# $setVMPropertyParams = @{ -# VMName = $mockVMName -# VMCommand = 'Set-VMProcessor' -# ChangeProperty = @{ -# ResourcePoolName = 'Dummy' -# } -# } - -# { Set-VMProperty @setVMPropertyParams } | Should -Throw ( -# $script:localizedData.CannotUpdatePropertiesOnlineError -f $mockVMName, 'Running' -# ) -# } - -# It "Should stop and restart VM when running and 'RestartIfNeeded' is True" { -# Mock -CommandName Stop-VM -# Mock -CommandName Set-VMProcessor -# Mock -CommandName Set-VMStateHvDsc -# Mock -CommandName Get-VM -MockWith { -# return @{ -# State = 'Running' -# } -# } - -# $setVMPropertyParams = @{ -# VMName = 'Test' -# VMCommand = 'Set-VMProcessor' -# ChangeProperty = @{ -# ResourcePoolName = 'Dummy' -# } -# RestartIfNeeded = $true -# } -# Set-VMProperty @setVMPropertyParams - -# Assert-MockCalled -CommandName Set-VMStateHvDsc -ParameterFilter { -# $State -eq 'Off' -# } -Scope It - -# Assert-MockCalled -CommandName Set-VMStateHvDsc -ParameterFilter { -# $State -eq 'Running' -# } -Scope It -# } -# } -# } diff --git a/tests/Unit/HyperVDsc.Common/Public/Set-VMState.Tests.ps1 b/tests/Unit/HyperVDsc.Common/Public/Set-VMState.Tests.ps1 new file mode 100644 index 0000000..46a0dd2 --- /dev/null +++ b/tests/Unit/HyperVDsc.Common/Public/Set-VMState.Tests.ps1 @@ -0,0 +1,130 @@ +#region HEADER +$script:projectPath = "$PSScriptRoot\..\..\..\.." | Convert-Path +$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and + $(try + { + Test-ModuleManifest -Path $_.FullName -ErrorAction Stop + } + catch + { + $false + }) + }).BaseName + +$script:parentModule = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 +$script:subModulesFolder = Join-Path -Path $script:parentModule.ModuleBase -ChildPath 'Modules' +Remove-Module -Name $script:parentModule -Force -ErrorAction 'SilentlyContinue' + +$script:subModuleName = ('{0}.Common' -f $script:projectName) +$script:subModuleFile = Join-Path -Path $script:subModulesFolder -ChildPath "$($script:subModuleName)" + +Import-Module $script:subModuleFile -Force -ErrorAction 'Stop' +#endregion HEADER + +# Import the stub functions. +#Get-Module -Name 'Hyper-V' -All | Remove-Module -Force +Import-Module -Name "$PSScriptRoot/../../Stubs/Hyper-V.stubs.psm1" -Force -DisableNameChecking + +InModuleScope $script:subModuleName { + Describe 'Public\Set-VMState' { + It 'Should resume VM when current "State" is "Paused" and target state is "Running"' { + Mock -CommandName Resume-VM + Mock -CommandName Wait-VMIPAddress + Mock -CommandName Get-VM -MockWith { + return @{ + State = 'Paused' + } + } + + Set-VMState -Name 'TestVM' -State 'Running' + + Assert-MockCalled -CommandName Resume-VM -Scope It + Assert-MockCalled -CommandName Wait-VMIPAddress -Scope It -Exactly 0 + } + + It 'Should resume VM and wait when current "State" is "Paused" and target state is "Running"' { + Mock -CommandName Resume-VM + Mock -CommandName Wait-VMIPAddress + Mock -CommandName Get-VM -MockWith { + return @{ + State = 'Paused' + } + } + + Set-VMState -Name 'TestVM' -State 'Running' -WaitForIP $true + + Assert-MockCalled -CommandName Resume-VM -Scope It + Assert-MockCalled -CommandName Wait-VMIPAddress -Scope It + } + + It 'Should start VM when current "State" is "Off" and target state is "Running"' { + Mock -CommandName Start-VM + Mock -CommandName Wait-VMIPAddress + Mock -CommandName Get-VM -MockWith { + return @{ + State = 'Off' + } + } + + Set-VMState -Name 'TestVM' -State 'Running' + + Assert-MockCalled -CommandName Start-VM -Scope It + Assert-MockCalled -CommandName Wait-VMIPAddress -Scope It -Exactly 0 + } + + It 'Should start VM and wait when current "State" is "Off" and target state is "Running"' { + Mock -CommandName Start-VM + Mock -CommandName Wait-VMIPAddress + Mock -CommandName Get-VM -MockWith { + return @{ + State = 'Off' + } + } + + Set-VMState -Name 'TestVM' -State 'Running' -WaitForIP $true + + Assert-MockCalled -CommandName Start-VM -Scope It + Assert-MockCalled -CommandName Wait-VMIPAddress -Scope It + } + + It 'Should suspend VM when current "State" is "Running" and target state is "Paused"' { + Mock -CommandName Suspend-VM + Mock -CommandName Get-VM -MockWith { + return @{ + State = 'Running' + } + } + + Set-VMState -Name 'TestVM' -State 'Paused' + + Assert-MockCalled -CommandName Suspend-VM -Scope It + } + + It 'Should stop VM when current "State" is "Running" and target state is "Off"' { + Mock -CommandName Stop-VM + Mock -CommandName Get-VM -MockWith { + return @{ + State = 'Running' + } + } + + Set-VMState -Name 'TestVM' -State 'Off' + + Assert-MockCalled -CommandName Stop-VM -Scope It + } + + It 'Should stop VM when current "State" is "Paused" and target state is "Off"' { + Mock -CommandName Stop-VM + Mock -CommandName Get-VM -MockWith { + return @{ + State = 'Paused' + } + } + + Set-VMState -Name 'TestVM' -State 'Off' + + Assert-MockCalled -CommandName Stop-VM -Scope It + } + } +} diff --git a/tests/Unit/HyperVDsc.Common/Public/Set-VMState.ps1 b/tests/Unit/HyperVDsc.Common/Public/Set-VMState.ps1 deleted file mode 100644 index fce2bf0..0000000 --- a/tests/Unit/HyperVDsc.Common/Public/Set-VMState.ps1 +++ /dev/null @@ -1,125 +0,0 @@ -# #region HEADER -# $script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path -# $script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { -# ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and -# $(try -# { -# Test-ModuleManifest -Path $_.FullName -ErrorAction Stop -# } -# catch -# { -# $false -# }) -# }).BaseName - -# $script:parentModule = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 - -# Import-Module $script:parentModule -Force -ErrorAction 'Stop' -# #endregion HEADER - -# # Import the stub functions. -# #Get-Module -Name 'Hyper-V' -All | Remove-Module -Force -# Import-Module -Name "$PSScriptRoot/../Stubs/Hyper-V.stubs.psm1" -Force - -# InModuleScope $script:parentModule { -# Describe 'Public\Set-VMState' { -# It 'Should resume VM when current "State" is "Paused" and target state is "Running"' { -# Mock -CommandName Resume-VM -# Mock -CommandName Wait-VMIPAddress -# Mock -CommandName Get-VM -MockWith { -# return @{ -# State = 'Paused' -# } -# } - -# Set-VMState -Name 'TestVM' -State 'Running' - -# Assert-MockCalled -CommandName Resume-VM -Scope It -# Assert-MockCalled -CommandName Wait-VMIPAddress -Scope It -Exactly 0 -# } - -# It 'Should resume VM and wait when current "State" is "Paused" and target state is "Running"' { -# Mock -CommandName Resume-VM -# Mock -CommandName Wait-VMIPAddress -# Mock -CommandName Get-VM -MockWith { -# return @{ -# State = 'Paused' -# } -# } - -# Set-VMState -Name 'TestVM' -State 'Running' -WaitForIP $true - -# Assert-MockCalled -CommandName Resume-VM -Scope It -# Assert-MockCalled -CommandName Wait-VMIPAddress -Scope It -# } - -# It 'Should start VM when current "State" is "Off" and target state is "Running"' { -# Mock -CommandName Start-VM -# Mock -CommandName Wait-VMIPAddress -# Mock -CommandName Get-VM -MockWith { -# return @{ -# State = 'Off' -# } -# } - -# Set-VMState -Name 'TestVM' -State 'Running' - -# Assert-MockCalled -CommandName Start-VM -Scope It -# Assert-MockCalled -CommandName Wait-VMIPAddress -Scope It -Exactly 0 -# } - -# It 'Should start VM and wait when current "State" is "Off" and target state is "Running"' { -# Mock -CommandName Start-VM -# Mock -CommandName Wait-VMIPAddress -# Mock -CommandName Get-VM -MockWith { -# return @{ -# State = 'Off' -# } -# } - -# Set-VMState -Name 'TestVM' -State 'Running' -WaitForIP $true - -# Assert-MockCalled -CommandName Start-VM -Scope It -# Assert-MockCalled -CommandName Wait-VMIPAddress -Scope It -# } - -# It 'Should suspend VM when current "State" is "Running" and target state is "Paused"' { -# Mock -CommandName Suspend-VM -# Mock -CommandName Get-VM -MockWith { -# return @{ -# State = 'Running' -# } -# } - -# Set-VMState -Name 'TestVM' -State 'Paused' - -# Assert-MockCalled -CommandName Suspend-VM -Scope It -# } - -# It 'Should stop VM when current "State" is "Running" and target state is "Off"' { -# Mock -CommandName Stop-VM -# Mock -CommandName Get-VM -MockWith { -# return @{ -# State = 'Running' -# } -# } - -# Set-VMState -Name 'TestVM' -State 'Off' - -# Assert-MockCalled -CommandName Stop-VM -Scope It -# } - -# It 'Should stop VM when current "State" is "Paused" and target state is "Off"' { -# Mock -CommandName Stop-VM -# Mock -CommandName Get-VM -MockWith { -# return @{ -# State = 'Paused' -# } -# } - -# Set-VMState -Name 'TestVM' -State 'Off' - -# Assert-MockCalled -CommandName Stop-VM -Scope It -# } -# } -# } From a7551076916a3d08f9950b8b913c1679e0f12fc7 Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Fri, 31 Jan 2025 16:49:57 +0000 Subject: [PATCH 5/6] Fix typos --- tests/Integration/DSC_VMHost_set.config.ps1 | 2 +- tests/Integration/DSC_VMProcessor_set.config.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Integration/DSC_VMHost_set.config.ps1 b/tests/Integration/DSC_VMHost_set.config.ps1 index e4d3fae..8a81404 100644 --- a/tests/Integration/DSC_VMHost_set.config.ps1 +++ b/tests/Integration/DSC_VMHost_set.config.ps1 @@ -15,7 +15,7 @@ configuration DSC_VMHost_Set_Config $EnableEnhancedSessionMode ) - Import-DscResource -ModuleName 'xHyperV' + Import-DscResource -ModuleName 'HyperVDsc' node localhost { VMHost Integration_Test { diff --git a/tests/Integration/DSC_VMProcessor_set.config.ps1 b/tests/Integration/DSC_VMProcessor_set.config.ps1 index 12c269b..6832121 100644 --- a/tests/Integration/DSC_VMProcessor_set.config.ps1 +++ b/tests/Integration/DSC_VMProcessor_set.config.ps1 @@ -3,7 +3,7 @@ configuration DSC_VMProcessor_Set_Config { Import-DscResource -ModuleName 'HyperVDsc' node localhost { - xVMProcessor Integration_Test { + VMProcessor Integration_Test { VMName = $Node.VMName CompatibilityForMigrationEnabled = $Node.CompatibilityForMigrationEnabled CompatibilityForOlderOperatingSystemsEnabled = $Node.CompatibilityForOlderOperatingSystemsEnabled From ab5d61feab353e33a5d3439948adba33a5b0ea1f Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Fri, 31 Jan 2025 16:52:24 +0000 Subject: [PATCH 6/6] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7184a62..68d06c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ For older change log history see the [historic changelog](HISTORIC_CHANGELOG.md) - Fix multiple DNS IP adresses does not work #190 - NetworkSetting parameter is now optional and no default actions are taken if not specified - Switch to use VM image `windows-latest` to build phase. + - Use latest DscCommunity scripts and files + - Changed `HyperVDsc.Common` to a buildable module. ## [3.18.0] - 2022-06-04