diff --git a/DSCResources/MSFT_xSQLAlias/MSFT_xSQLAlias.psm1 b/DSCResources/MSFT_xSQLAlias/MSFT_xSQLAlias.psm1 index ace2f0ecc2..2c196e6c3f 100644 --- a/DSCResources/MSFT_xSQLAlias/MSFT_xSQLAlias.psm1 +++ b/DSCResources/MSFT_xSQLAlias/MSFT_xSQLAlias.psm1 @@ -19,35 +19,54 @@ function Get-TargetResource $ServerName ) - Write-Verbose -Message 'Get-TargetResource' - $returnValue = @{ - Name = [System.String] - Protocol = [System.String] - ServerName = [System.String] - TCPPort = [System.Int32] - PipeName = [System.String] - Ensure = [System.String] + Name = [System.String] $Name + Protocol = [System.String] '' + ServerName = [System.String] '' + TcpPort = [System.UInt16] 0 + PipeName = [System.String] '' + Ensure = [System.String] 'Absent' } - if ($null -ne (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo' -Name $Name -ErrorAction SilentlyContinue)) + $protocolTcp = 'DBMSSOCN' + $protocolNamedPipes = 'DBNMPNTW' + + Write-Verbose "Get the client alias $Name" + + <# + Get-ItemProperty will either return $null if no value is set, or if value is set, it will always + return a value in the format 'DBNMPNTW,\\ServerName\PIPE\sql\query' or 'DBMSSOCN,ServerName.company.local,1433' + #> + $itemValue = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo' -Name $Name -ErrorAction SilentlyContinue + if ((Get-WmiOSArchitecture) -eq '64-bit') { - $itemValue = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo' -Name $Name -ErrorAction SilentlyContinue + Write-Verbose "64-bit Operating System. Also get the client alias $Name from Wow6432Node" - $returnValue.Name = $Name - $itemConfig = $itemValue."$Name" -split ',' - if ($itemConfig[0] -eq 'DBMSSOCN') - { - $returnValue.Protocol = 'TCP' - $returnValue.ServerName = $itemConfig[1] - $returnValue.TCPPort = $itemConfig[2] - } - else + $isWow6432Node = $true + $itemValueWow6432Node = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo' -Name $Name -ErrorAction SilentlyContinue + } + + if ((-not $isWow6432Node -and $null -ne $itemValue ) -or + ( ($null -ne $itemValue -and $null -ne $itemValueWow6432Node) -and + ($isWow6432Node -and $itemValueWow6432Node."$Name" -eq $itemValue."$Name") )) + { + $itemConfig = $itemValue."$Name" | ConvertFrom-Csv -Header 'Protocol','ServerName','TcpPort' + if ($itemConfig) { - $returnValue.Protocol = 'NP' - $returnValue.PipeName = $itemConfig[1] + if ($itemConfig.Protocol -eq $protocolTcp) + { + $returnValue.Ensure = 'Present' + $returnValue.Protocol = 'TCP' + $returnValue.ServerName = $itemConfig.ServerName + $returnValue.TcpPort = $itemConfig.TcpPort + } + elseif ($itemConfig.Protocol -eq $protocolNamedPipes) + { + $returnValue.Ensure = 'Present' + $returnValue.Protocol = 'NP' + $returnValue.PipeName = $itemConfig.ServerName + } } - } $returnValue @@ -65,25 +84,21 @@ function Set-TargetResource [ValidateSet("TCP","NP")] [System.String] - $Protocol, + $Protocol = 'TCP', [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $ServerName, - [System.Int32] - $TCPPort, + [System.UInt16] + $TcpPort = 1433, [ValidateSet("Present","Absent")] [System.String] - $Ensure + $Ensure = 'Present' ) - Write-Verbose -Message 'Set-TargetResource' - - $itemValue = [System.String] - if ($Protocol -eq 'NP') { $itemValue = "DBNMPNTW,\\$ServerName\PIPE\sql\query" @@ -91,93 +106,55 @@ function Set-TargetResource if ($Protocol -eq 'TCP') { - $itemValue = "DBMSSOCN,$ServerName,$TCPPort" + $itemValue = "DBMSSOCN,$ServerName,$TcpPort" } - # Logic based on ensure value Present + $registryPath = 'HKLM:\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo' + $registryPathWow6432Node = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo' + if ($Ensure -eq 'Present') { - Write-Debug -Message 'Check if value requires changing' - - $currentValue = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo' -Name $Name -ErrorAction SilentlyContinue - if ($null -ne $currentValue -and $itemValue -ne $currentValue) + if ($PSCmdlet.ShouldProcess($Name, 'Setting the client alias')) { - if ($PSCmdlet.ShouldProcess($Name,"Changing the client alias (64-bit)")) + if (!(Test-Path -Path $registryPath)) { - Write-Debug -Message 'Set-ItemProperty' - Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo' -Name $Name -Value $itemValue + New-Item -Path $registryPath | Out-Null } - } - elseif ($null -eq $currentValue) - { - if ($PSCmdlet.ShouldProcess($Name,"Create client alias (64-bit)")) - { - if (!(Test-Path 'HKLM:\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo')) - { - Write-Debug -Message 'New-Item' - New-Item -Path 'HKLM:\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo' | Out-Null - } - Write-Debug -Message 'New-ItemProperty' - New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo' -Name $Name -Value $itemValue | Out-Null - } + Set-ItemProperty -Path $registryPath -Name $Name -Value $itemValue | Out-Null } - Write-Debug -Message 'Check OSArchitecture' - # If this is a 64 bit machine also update Wow6432Node - if ((Get-Wmiobject -Class win32_OperatingSystem).OSArchitecture -eq '64-bit') + # If this is a 64-bit OS then also update Wow6432Node + if ((Get-WmiOSArchitecture) -eq '64-bit') { - Write-Debug -Message 'Is 64Bit' - Write-Debug -Message 'Check if value requires changing' - $currentValue = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo' -Name $Name -ErrorAction SilentlyContinue - if ($null -ne $currentValue -and $itemValue -ne $currentValue) + if ($PSCmdlet.ShouldProcess($Name, 'Setting the client alias (32-bit)')) { - if ($PSCmdlet.ShouldProcess($Name,"Changing the client alias (32-bit)")) + if (!(Test-Path -Path $registryPathWow6432Node)) { - Write-Debug -Message 'Set-ItemProperty' - Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo' -Name $Name -Value $itemValue + New-Item -Path $registryPathWow6432Node | Out-Null } - } - elseif ($null -eq $currentValue) - { - if ($PSCmdlet.ShouldProcess($Name,"Create client alias (32-bit)")) - { - if (!(Test-Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo')) - { - Write-Debug -Message 'New-Item' - New-Item -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo' | Out-Null - } - Write-Debug -Message 'New-ItemProperty' - New-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo' -Name $Name -Value $itemValue - } + Set-ItemProperty -Path $registryPathWow6432Node -Name $Name -Value $itemValue | Out-Null } } } - # Logic based on ensure value Absent if ($Ensure -eq 'Absent') { - # If the base path doesn't exist then we don't need to do anything - if (Test-Path 'HKLM:\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo') + if ($PSCmdlet.ShouldProcess($Name, 'Remove the client alias')) { - - if ($PSCmdlet.ShouldProcess($Name,"Remove the client alias (64-bit)")) + if (Test-Path -Path $registryPath) { - Write-Debug -Message 'Remove-ItemProperty' - Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo' -Name $Name + Remove-ItemProperty -Path $registryPath -Name $Name } + } - Write-Debug -Message 'Check OSArchitecture' - - # If this is a 64 bit machine also update Wow6432Node - if ((Get-Wmiobject -Class win32_OperatingSystem).OSArchitecture -eq '64-bit' -and (Test-Path -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo')) + # If this is a 64-bit OS then also remove from Wow6432Node + if ((Get-WmiOSArchitecture) -eq '64-bit' -and (Test-Path -Path $registryPathWow6432Node)) + { + if ($PSCmdlet.ShouldProcess($Name, 'Remove the client alias (32-bit)')) { - if ($PSCmdlet.ShouldProcess($Name,"Remove the client alias (34-bit)")) - { - Write-Debug -Message 'Remove-ItemProperty Wow6432Node' - Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo' -Name $Name - } + Remove-ItemProperty -Path $registryPathWow6432Node -Name $Name } } } @@ -196,160 +173,73 @@ function Test-TargetResource [ValidateSet("TCP","NP")] [System.String] - $Protocol, + $Protocol = 'TCP', [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $ServerName, - [System.Int32] - $TCPPort, + [System.UInt16] + $TcpPort = 1433, [ValidateSet("Present","Absent")] [System.String] - $Ensure + $Ensure = 'Present' ) - Write-Debug -Message 'Test-TargetResource' - - $result = [System.Boolean] $true + $result = $false - if (Test-Path -Path 'HKLM:\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo') + $currentValues = Get-TargetResource -Name $Name -ServerName $ServerName + if ($Ensure -eq $currentValues.Ensure) { - Write-Debug -Message 'Alias registry container exists' - if ($null -ne (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo' -Name $Name -ErrorAction SilentlyContinue)) + if( $Ensure -eq 'Absent' ) { - Write-Debug -Message 'Existing alias found' - if ($Ensure -eq 'Present') - { - $itemValue = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo' -Name $Name -ErrorAction SilentlyContinue - - $itemConfig = $itemValue."$Name" -split ',' - - if ($Protocol -eq 'NP') - { - Write-Debug -Message 'Named Pipes' - - if ($itemConfig[0] -ne 'DBNMPNTW') - { - $result = $false - } - - if ($itemConfig[1] -ne "\\$ServerName\PIPE\sql\query") - { - $result = $false - } - } - - if ($Protocol -eq 'TCP') - { - Write-Debug -Message 'TCP' - if ($itemConfig[0] -ne 'DBMSSOCN') - { - $result = $false - } - - if ($itemConfig[1] -ne $ServerName) - { - $result = $false - } - - if ($itemConfig[2] -ne $TCPPort) - { - $result = $false - } - } + $result = $true + } + else { + Write-Verbose "Ensure is in the desired state. Verifying values." - # If this is a 64 bit machine also check Wow6432Node - if ((Get-Wmiobject -Class win32_OperatingSystem).OSArchitecture -eq '64-bit') + if ($Protocol -eq $currentValues.Protocol) + { + switch ($Protocol) { - Write-Debug -Message 'Wow6432Node' - if ($null -ne (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo' -Name $Name -ErrorAction SilentlyContinue)) + 'NP' { - Write-Debug -Message 'Existing alias found' - $itemValue = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo' -Name $Name -ErrorAction SilentlyContinue - - $itemConfig = $itemValue."$Name" -split ',' - - if ($Protocol -eq 'NP') + if ($currentValues.PipeName -eq "\\$ServerName\PIPE\sql\query") { - Write-Debug -Message 'Named Pipes' - - if ($itemConfig[0] -ne 'DBNMPNTW') - { - $result = $false - } - - if ($itemConfig[1] -ne "\\$ServerName\PIPE\sql\query") - { - $result = $false - } + $result = $true } + } - if ($Protocol -eq 'TCP') + 'TCP' + { + if ($currentValues.ServerName -eq $ServerName -and + $currentValues.TcpPort -eq $TcpPort) { - Write-Debug -Message 'TCP' - - if ($itemConfig[0] -ne 'DBMSSOCN') - { - $result = $false - } - - if ($itemConfig[1] -ne $ServerName) - { - $result = $false - } - - if ($itemConfig[2] -ne $TCPPort) - { - $result = $false - } + $result = $true } } - else - { - # Wow6432Node - $result = $false - } } } - else - { - # Existing alias not found - $result = $false - } - } - else - { - # Registry container doesn't exist - if ($Ensure -eq 'Present') - { - $result = $false - } - else - { - $result = $true - } } } + + if ($result) + { + Write-Verbose "In the desired state" + } else { - # Alias not present - if ($Ensure -eq 'Present') - { - $result = $false - } - else - { - $result = $true - } + Write-Verbose "Not in the desired state" } - Write-Debug -Message "Test-TargetResource Result: $result" - return $result } +function Get-WmiOSArchitecture +{ + return (Get-WmiObject -Class win32_OperatingSystem).OSArchitecture +} Export-ModuleMember -Function *-TargetResource diff --git a/DSCResources/MSFT_xSQLAlias/MSFT_xSQLAlias.schema.mof b/DSCResources/MSFT_xSQLAlias/MSFT_xSQLAlias.schema.mof index b62ca6dfac..b02929ad3c 100644 --- a/DSCResources/MSFT_xSQLAlias/MSFT_xSQLAlias.schema.mof +++ b/DSCResources/MSFT_xSQLAlias/MSFT_xSQLAlias.schema.mof @@ -2,9 +2,9 @@ class MSFT_xSQLAlias : OMI_BaseResource { [Key, Description("The name of Alias (e.g. svr01\\inst01).")] String Name; - [Write, Description("Protocol to use when connecting. Valid values are TCP or NP. NP is Named Pipes."), ValueMap{"TCP","NP"}, Values{"TCP","NP"}] String Protocol; - [Key, Description("The SQL Server you are aliasing (the real SQL Server name).")] String ServerName; - [Write, Description("The TCP port SQL is listening on.")] Sint32 TCPPort; - [Read, Description("Named Pipes name from the Get-TargetResource method.")] String PipeName; - [Write, Description("Determines whether the alias should be added or removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; + [Write, Description("Protocol to use when connecting. Valid values are 'TCP' or 'NP' (Named Pipes). Default values is 'TCP'."), ValueMap{"TCP","NP"}, Values{"TCP","NP"}] String Protocol; + [Key, Description("The SQL Server you are aliasing (the netbios name or FQDN).")] String ServerName; + [Write, Description("The TCP port SQL is listening on. Only used when protocol is set to 'TCP'. Default value is port 1433.")] UInt16 TcpPort; + [Read, Description("Named Pipes path from the Get-TargetResource method.")] String PipeName; + [Write, Description("Determines whether the alias should be added or removed. Default values is 'Present'"), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; }; diff --git a/README.md b/README.md index 9d05efcb26..c3c2276d69 100644 --- a/README.md +++ b/README.md @@ -330,12 +330,12 @@ Please check out common DSC Resources [contributing guidelines](https://github.c * **Variable**: Creates a sqlcmd scripting variable for use in the sqlcmd script, and sets a value for the variable. ### xSqlAlias - * **Ensure**: Determines whether the alias should be added or removed. + * **Ensure**: Determines whether the alias should be added or removed. Default values is 'Present' * **Name**: (Key) The name of Alias (e.g. svr01\inst01). - * **ServerName**: (Key) The SQL Server you are aliasing (the real SQL Server name). - * **Protocol**: Protocol to use when connecting. Valid values are TCP or NP. NP is Named Pipes. - * **TCPPort**: The TCP port SQL is listening on. - * **PipeName**: (Readonly) Named Pipes name from the Get-TargetResource method. + * **ServerName**: (Key) The SQL Server you are aliasing (the netbios name or FQDN). + * **Protocol**: Protocol to use when connecting. Valid values are 'TCP' or 'NP' (Named Pipes). Default values is 'TCP'. + * **TCPPort**: The TCP port SQL is listening on. Only used when protocol is set to 'TCP'. Default value is port 1433. + * **PipeName**: (Read) Named Pipes path from the Get-TargetResource method. ## Versions @@ -343,7 +343,7 @@ Please check out common DSC Resources [contributing guidelines](https://github.c * Added resources - xSQLServerReplication - xSQLServerScript - - xSQLAlias + - xSqlAlias * Added tests for resources - xSQLServerPermission - xSQLServerEndpointState @@ -351,7 +351,7 @@ Please check out common DSC Resources [contributing guidelines](https://github.c - xSQLServerAvailabilityGroupListener - xSQLServerLogin - xSQLAOGroupEnsure - - xSQLAlias + - xSqlAlias * Fixes in xSQLServerAvailabilityGroupListener - In one case the Get-method did not report that DHCP was configured. - Now the resource will throw 'Not supported' when IP is changed between Static and DHCP. diff --git a/Tests/Unit/MSFT_xSqlAlias.Tests.ps1 b/Tests/Unit/MSFT_xSqlAlias.Tests.ps1 index 7a5d39d213..5e2e1d692b 100644 --- a/Tests/Unit/MSFT_xSqlAlias.Tests.ps1 +++ b/Tests/Unit/MSFT_xSqlAlias.Tests.ps1 @@ -23,117 +23,784 @@ $TestEnvironment = Initialize-TestEnvironment ` try { #region Pester Test Initialization + $registryPath = 'HKLM:\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo' + $registryPathWow6432Node = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo' + + $name = 'MyAlias' + $serverNameTcp = 'sqlnode.company.local' + $tcpPort = 1433 + $serverNameNamedPipes = 'sqlnode' + $pipeName = "\\$serverNameNamedPipes\PIPE\sql\query" + + $unknownName = 'UnknownAlias' + $unknownServerName = 'unknownserver' + + $nameDifferentTcpPort = 'DifferentTcpPort' + $nameDifferentServerNameTcp = 'DifferentServerNameTcp' + $nameDifferentPipeName = 'DifferentPipeName' + $differentTcpPort = 1500 + $differentServerNameTcp = "$unknownServerName.company.local" + $differentPipeName = "\\$unknownServerName\PIPE\sql\query" + + $nameWow6432NodeDifferFrom64BitOS = 'Wow6432NodeDifferFrom64BitOS' #endregion Pester Test Initialization #region Get-TargetResource - Describe 'Get-TargetResource' { - Mock -CommandName Get-ItemProperty -MockWith { - return 'DBMSSOCN,localhost,1433' - } -ModuleName $script:DSCResourceName - - $SqlAlias = Get-TargetResource -Name 'localhost' -Servername 'localhost' + Describe "$($script:DSCResourceName)\Get-TargetResource" { + # Mocking for protocol TCP + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPath -and $Name -eq $name } -MockWith { + return @{ + 'MyAlias' = 'DBMSSOCN,sqlnode.company.local,1433' + } + } -ModuleName $script:DSCResourceName -Verifiable + + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPathWow6432Node -and $Name -eq $name } -MockWith { + return @{ + 'MyAlias' = 'DBMSSOCN,sqlnode.company.local,1433' + } + } -ModuleName $script:DSCResourceName -Verifiable + + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPath -and $Name -eq $nameDifferentTcpPort } -MockWith { + return @{ + 'DifferentTcpPort' = 'DBMSSOCN,sqlnode.company.local,1500' + } + } -ModuleName $script:DSCResourceName -Verifiable + + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPathWow6432Node -and $Name -eq $nameDifferentTcpPort } -MockWith { + return @{ + 'DifferentTcpPort' = 'DBMSSOCN,sqlnode.company.local,1500' + } + } -ModuleName $script:DSCResourceName -Verifiable + + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPath -and $Name -eq $nameDifferentServerNameTcp } -MockWith { + return @{ + 'DifferentServerNameTcp' = 'DBMSSOCN,unknownserver.company.local,1433' + } + } -ModuleName $script:DSCResourceName -Verifiable + + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPathWow6432Node -and $Name -eq $nameDifferentServerNameTcp } -MockWith { + return @{ + 'DifferentServerNameTcp' = 'DBMSSOCN,unknownserver.company.local,1433' + } + } -ModuleName $script:DSCResourceName -Verifiable + + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPath -and $Name -eq $unknownName } -MockWith { + return $null + } -ModuleName $script:DSCResourceName -Verifiable + + # Mocking 64-bit OS + Mock -CommandName Get-WmiObject -MockWith { + return New-Object Object | + Add-Member -MemberType NoteProperty -Name OSArchitecture -Value '64-bit' -PassThru -Force + } -ParameterFilter { $Class -eq 'win32_OperatingSystem' } -ModuleName $script:DSCResourceName -Verifiable + + Context 'When the system is in the desired present state for 64-bit OS using TCP' { + $testParameters = @{ + Name = $name + ServerName = $serverNameTcp + } + + $result = Get-TargetResource @testParameters + + It 'Should return the state as present' { + $result.Ensure | Should Be 'Present' + } + + It 'Should return the same values as passed as parameters' { + $result.Name | Should Be $testParameters.Name + $result.ServerName | Should Be $testParameters.ServerName + } + + It 'Should return TCP as the protocol used' { + $result.Protocol | Should Be 'TCP' + } + + It "Should return $tcpPort as the port number used" { + $result.TcpPort | Should Be $tcpPort + } - It 'Should return hashtable with Key Protocol'{ - $SqlAlias.ContainsKey('Protocol') | Should Be $true + It 'Should not return any pipe name' { + $result.PipeName | Should Be '' + } + + It 'Should call the mocked functions exactly 1 time each' { + Assert-MockCalled Get-WmiObject -ParameterFilter { $Class -eq 'win32_OperatingSystem' } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPath } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPathWow6432Node } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + } } - - It 'Should return hashtable with Value that matches "TCP"'{ - $SqlAlias.Protocol = 'TCP' + + Context 'When the system is in the desired absent state for 64-bit OS' { + $testParameters = @{ + Name = $unknownName + ServerName = $unknownServerName + } + + $result = Get-TargetResource @testParameters + + It 'Should return the state as absent' { + $result.Ensure | Should Be 'Absent' + } + + It 'Should return the same values as passed as parameters' { + $result.Name | Should Be $testParameters.Name + } + + It 'Should not return the value passed in the ServerName parameter' { + $result.ServerName | Should Be '' + } + + It 'Should not return any protocol' { + $result.Protocol | Should Be '' + } + + It 'Should not return a port number' { + $result.TcpPort | Should Be 0 + } + + It 'Should not return any pipe name' { + $result.PipeName | Should Be '' + } + + It 'Should call the mocked functions exactly 1 time each' { + Assert-MockCalled Get-WmiObject -ParameterFilter { $Class -eq 'win32_OperatingSystem' } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPath } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPathWow6432Node } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + } } - } - #end region Get-TargetResource - #region Set-TargetResource - Describe 'Set-TargetResource' { - Mock -CommandName New-ItemProperty -MockWith {} -ModuleName $script:DSCResourceName - Mock -CommandName Set-ItemProperty -MockWith {} -ModuleName $script:DSCResourceName - Mock -CommandName Remove-ItemProperty -MockWith {} -ModuleName $script:DSCResourceName - - Mock -CommandName Test-Path -MockWith { - return $true - } -ModuleName $script:DSCResourceName + Context 'When the system is not in the desired state because TcpPort is different when desired protocol is TCP' { + $testParameters = @{ + Name = $nameDifferentTcpPort + ServerName = $serverNameTcp + } + + $result = Get-TargetResource @testParameters + + It 'Should return the state as present' { + $result.Ensure | Should Be 'Present' + } + It 'Should return the same values as passed as parameters' { + $result.Name | Should Be $testParameters.Name + $result.ServerName | Should Be $testParameters.ServerName + } + + It 'Should return TCP as the protocol used' { + $result.Protocol | Should Be 'TCP' + } + + It "Should return $differentTcpPort as the port number used" { + $result.TcpPort | Should Be $differentTcpPort + } + + It 'Should not return any pipe name' { + $result.PipeName | Should Be '' + } + + It 'Should call the mocked functions exactly 1 time each' { + Assert-MockCalled Get-WmiObject -ParameterFilter { $Class -eq 'win32_OperatingSystem' } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPath } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPathWow6432Node } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + } + } + + Context 'When the system is not in the desired state because ServerName is different when desired protocol is TCP' { + $testParameters = @{ + Name = $nameDifferentServerNameTcp + ServerName = $serverNameTcp + } + + $result = Get-TargetResource @testParameters + + It 'Should return the state as present' { + $result.Ensure | Should Be 'Present' + } + + It 'Should return the same values as passed as parameters' { + $result.Name | Should Be $testParameters.Name + } + + It 'Should return different server name than the one passed as parameter' { + $result.ServerName | Should Be $differentServerNameTcp + } + + It 'Should return TCP as the protocol used' { + $result.Protocol | Should Be 'TCP' + } + + It "Should return $tcpPort as the port number used" { + $result.TcpPort | Should Be $tcpPort + } + + It 'Should not return any pipe name' { + $result.PipeName | Should Be '' + } + + It 'Should call the mocked functions exactly 1 time each' { + Assert-MockCalled Get-WmiObject -ParameterFilter { $Class -eq 'win32_OperatingSystem' } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPath } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPathWow6432Node } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + } + } + + # Mocking 32-bit OS Mock -CommandName Get-WmiObject -MockWith { + return New-Object Object | + Add-Member -MemberType NoteProperty -Name OSArchitecture -Value '32-bit' -PassThru -Force + } -ParameterFilter { $Class -eq 'win32_OperatingSystem' } -ModuleName $script:DSCResourceName -Verifiable + + Context 'When the system is in the desired present state for 32-bit OS using TCP' { + $testParameters = @{ + Name = $name + ServerName = $serverNameTcp + } + + $result = Get-TargetResource @testParameters + + It 'Should return the state as present' { + $result.Ensure | Should Be 'Present' + } + + It 'Should return the same values as passed as parameters' { + $result.Name | Should Be $testParameters.Name + $result.ServerName | Should Be $testParameters.ServerName + } + + It 'Should return TCP as the protocol used' { + $result.Protocol | Should Be 'TCP' + } + + It "Should return $tcpPort as the port number used" { + $result.TcpPort | Should Be $tcpPort + } + + It 'Should not return any pipe name' { + $result.PipeName | Should Be '' + } + + It 'Should call the mocked functions exactly 1 time each' { + Assert-MockCalled Get-WmiObject -ParameterFilter { $Class -eq 'win32_OperatingSystem' } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPath } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + } + + It 'Should not call the Get-ItemProperty for the Wow6432Node-path' { + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPathWow6432Node } ` + -Exactly -Times 0 -ModuleName $script:DSCResourceName -Scope Context + } + } + + Context 'When the system is in the desired absent state for 32-bit OS' { + $testParameters = @{ + Name = $unknownName + ServerName = $unknownServerName + } + + $result = Get-TargetResource @testParameters + + It 'Should return the state as absent' { + $result.Ensure | Should Be 'Absent' + } + + It 'Should return the same values as passed as parameters' { + $result.Name | Should Be $testParameters.Name + } + + It 'Should not return the value passed in the ServerName parameter' { + $result.ServerName | Should Be '' + } + + It 'Should not return any protocol' { + $result.Protocol | Should Be '' + } + + It 'Should not return a port number' { + $result.TcpPort | Should Be 0 + } + + It 'Should not return any pipe name' { + $result.PipeName | Should Be '' + } + + It 'Should call the mocked functions exactly 1 time each' { + Assert-MockCalled Get-WmiObject -ParameterFilter { $Class -eq 'win32_OperatingSystem' } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPath } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + } + + It 'Should not call the Get-ItemProperty for the Wow6432Node-path' { + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPathWow6432Node } ` + -Exactly -Times 0 -ModuleName $script:DSCResourceName -Scope Context + } + } + + # Testing protocol NP (Named Pipes) + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPath -and $Name -eq $name } -MockWith { return @{ - Class = 'win32_OperatingSystem' - OSArchitecture = '64-bit' + 'MyAlias' = 'DBNMPNTW,\\sqlnode\PIPE\sql\query' } - } -ModuleName $script:DSCResourceName + } -ModuleName $script:DSCResourceName -Verifiable - It 'Should call New-ItemProperty when value is not set' { - Mock -CommandName Get-ItemProperty -MockWith { - return $null - } -ModuleName $script:DSCResourceName + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPathWow6432Node -and $Name -eq $name } -MockWith { + return @{ + 'MyAlias' = 'DBNMPNTW,\\sqlnode\PIPE\sql\query' + } + } -ModuleName $script:DSCResourceName -Verifiable + + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPath -and $Name -eq $nameDifferentPipeName } -MockWith { + return @{ + 'DifferentPipeName' = 'DBNMPNTW,\\unknownserver\PIPE\sql\query' + } + } -ModuleName $script:DSCResourceName -Verifiable + + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPathWow6432Node -and $Name -eq $nameDifferentPipeName } -MockWith { + return @{ + 'DifferentPipeName' = 'DBNMPNTW,\\unknownserver\PIPE\sql\query' + } + } -ModuleName $script:DSCResourceName -Verifiable + + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPath -and $Name -eq $nameWow6432NodeDifferFrom64BitOS } -MockWith { + return @{ + 'Wow6432NodeDifferFrom64BitOS' = 'DBNMPNTW,\\firstserver\PIPE\sql\query' + } + } -ModuleName $script:DSCResourceName -Verifiable - Set-TargetResource -Name 'myServerAlias' -Protocol 'TCP' -ServerName 'localhost' -TCPPort 52002 -Ensure 'Present' + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPathWow6432Node -and $Name -eq $nameWow6432NodeDifferFrom64BitOS } -MockWith { + return @{ + 'Wow6432NodeDifferFrom64BitOS' = 'DBNMPNTW,\\secondserver\PIPE\sql\query' + } + } -ModuleName $script:DSCResourceName -Verifiable + + # Mocking 64-bit OS + Mock -CommandName Get-WmiObject -MockWith { + return New-Object Object | + Add-Member -MemberType NoteProperty -Name OSArchitecture -Value '64-bit' -PassThru -Force + } -ParameterFilter { $Class -eq 'win32_OperatingSystem' } -ModuleName $script:DSCResourceName -Verifiable - Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName New-ItemProperty -Exactly 2 -Scope It - Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Set-ItemProperty -Exactly 0 -Scope It + Context 'When the system is in the desired present state for 64-bit OS using Named Pipes' { + $testParameters = @{ + Name = $name + ServerName = $serverNameNamedPipes + } + + $result = Get-TargetResource @testParameters + + It 'Should return the state as present' { + $result.Ensure | Should Be 'Present' + } + + It 'Should return the same value as passed in the Name parameter' { + $result.Name | Should Be $testParameters.Name + } + + It 'Should not return the value passed in the ServerName parameter' { + $result.ServerName | Should Be '' + } + + It 'Should return NP as the protocol used' { + $result.Protocol | Should Be 'NP' + } + + It 'Should not return a port number' { + $result.TcpPort | Should Be 0 + } + + It 'Should return the correct pipe name based on the passed ServerName parameter' { + $result.PipeName | Should Be "\\$serverNameNamedPipes\PIPE\sql\query" + } + + It 'Should call the mocked functions exactly 1 time each' { + Assert-MockCalled Get-WmiObject -ParameterFilter { $Class -eq 'win32_OperatingSystem' } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPath } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPathWow6432Node } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + } } - Mock -CommandName Get-ItemProperty -MockWith { - return 'DBMSSOCN,localhost,52002' - } -ModuleName $script:DSCResourceName + Context 'When the system is not in the desired state because ServerName is different when desired protocol is Named Pipes' { + $testParameters = @{ + Name = $nameDifferentPipeName + ServerName = $serverNameNamedPipes + } + + $result = Get-TargetResource @testParameters - It 'Should not call any *-ItemProperty when value is already set' { - Set-TargetResource -Name 'myServerAlias' -Protocol 'TCP' -ServerName 'localhost' -TCPPort 52002 -Ensure 'Present' + It 'Should return the state as present' { + $result.Ensure | Should Be 'Present' + } - Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Set-ItemProperty -Exactly 0 -Scope It - Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName New-ItemProperty -Exactly 0 -Scope It - Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Remove-ItemProperty -Exactly 0 -Scope It + It 'Should return the same values as passed as parameters' { + $result.Name | Should Be $testParameters.Name + } + + It 'Should not return the value passed in the ServerName parameter' { + $result.ServerName | Should Be '' + } + + It 'Should return NP as the protocol used' { + $result.Protocol | Should Be 'NP' + } + + It 'Should not return a port number' { + $result.TcpPort | Should Be 0 + } + + It 'Should return the correct pipe name based on the passed ServerName parameter' { + $result.PipeName | Should Be $differentPipeName + } + + It 'Should call the mocked functions exactly 1 time each' { + Assert-MockCalled Get-WmiObject -ParameterFilter { $Class -eq 'win32_OperatingSystem' } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPath } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPathWow6432Node } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + } } - It 'Should call Set-ItemProperty exactly 2 times (1 for 32bit and 1 for 64 bit reg keys) when server name is different' { - Set-TargetResource -Name 'myServerAlias' -Protocol 'TCP' -ServerName 'newserver' -TCPPort 52002 -Ensure 'Present' + Context 'When the state differ between 32-bit OS and 64-bit OS registry keys' { + $testParameters = @{ + Name = $nameWow6432NodeDifferFrom64BitOS + ServerName = $serverNameNamedPipes + } + + $result = Get-TargetResource @testParameters + + It 'Should return the state as absent' { + $result.Ensure | Should Be 'Absent' + } + + It 'Should return the same values as passed as parameters' { + $result.Name | Should Be $testParameters.Name + } + + It 'Should not return the value passed in the ServerName parameter' { + $result.ServerName | Should Be '' + } + + It 'Should not return any protocol' { + $result.Protocol | Should Be '' + } + + It 'Should not return a port number' { + $result.TcpPort | Should Be 0 + } + + It 'Should not return any pipe name' { + $result.PipeName | Should Be '' + } + + It 'Should call the mocked functions exactly 1 time each' { + Assert-MockCalled Get-WmiObject -ParameterFilter { $Class -eq 'win32_OperatingSystem' } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context - Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Set-ItemProperty -Exactly 2 -Scope It - Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName New-ItemProperty -Exactly 0 -Scope It + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPath } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPathWow6432Node } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + } } - It 'Should call Set-ItemProperty exactly 2 times (1 for 32bit and 1 for 64 bit reg keys) when TCP port is different' { - Set-TargetResource -Name 'myServerAlias' -Protocol 'TCP' -ServerName 'localhost' -TCPPort 1433 -Ensure 'Present' + # Mocking 32-bit OS + Mock -CommandName Get-WmiObject -MockWith { + return New-Object Object | + Add-Member -MemberType NoteProperty -Name OSArchitecture -Value '32-bit' -PassThru -Force + } -ParameterFilter { $Class -eq 'win32_OperatingSystem' } -ModuleName $script:DSCResourceName -Verifiable + + Context 'When the system is in the desired present state for 32-bit OS using Named Pipes' { + $testParameters = @{ + Name = $name + ServerName = $serverNameNamedPipes + } + + $result = Get-TargetResource @testParameters + + It 'Should return the state as present' { + $result.Ensure | Should Be 'Present' + } + + It 'Should return the same value as passed in the Name parameter' { + $result.Name | Should Be $testParameters.Name + } + + It 'Should not return the value passed in the ServerName parameter' { + $result.ServerName | Should Be '' + } + + It 'Should return NP as the protocol used' { + $result.Protocol | Should Be 'NP' + } - Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Set-ItemProperty -Exactly 2 -Scope It + It 'Should not return a port number' { + $result.TcpPort | Should Be 0 + } + + It 'Should return the correct pipe name based on the passed ServerName parameter' { + $result.PipeName | Should Be $pipeName + } + + It 'Should call the mocked functions exactly 1 time each' { + Assert-MockCalled Get-WmiObject -ParameterFilter { $Class -eq 'win32_OperatingSystem' } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPath } ` + -Exactly -Times 1 -ModuleName $script:DSCResourceName -Scope Context + } + + It 'Should not call the Get-ItemProperty for the Wow6432Node-path' { + Assert-MockCalled Get-ItemProperty -ParameterFilter { $Path -eq $registryPathWow6432Node } ` + -Exactly -Times 0 -ModuleName $script:DSCResourceName -Scope Context + } } - It 'Should call any Remove-ItemProperty exactly 2 times (1 for 32bit and 1 for 64 bit reg keys) when alias should be absent' { - Set-TargetResource -Name 'myServerAlias' -Protocol 'TCP' -ServerName 'localhost' -TCPPort 52002 -Ensure 'Absent' + Assert-VerifiableMocks + } + #endregion Get-TargetResource + + #region Set-TargetResource + Describe "$($script:DSCResourceName)\Set-TargetResource" { + Mock -CommandName New-Item -MockWith {} -ModuleName $script:DSCResourceName -Verifiable + Mock -CommandName Set-ItemProperty -MockWith {} -ModuleName $script:DSCResourceName -Verifiable + Mock -CommandName Remove-ItemProperty -MockWith {} -ModuleName $script:DSCResourceName -Verifiable + Mock -CommandName Test-Path -MockWith { + return $false + } -ModuleName $script:DSCResourceName -Verifiable + + # Mocking 64-bit OS + Mock -CommandName Get-WmiObject -MockWith { + return New-Object Object | + Add-Member -MemberType NoteProperty -Name OSArchitecture -Value '64-bit' -PassThru -Force + } -ParameterFilter { $Class -eq 'win32_OperatingSystem' } -ModuleName $script:DSCResourceName -Verifiable + + Context 'When the system is not in the desired state for 64-bit OS using TCP' { + It 'Should call mocked functions Test-Path, New-Item and Set-ItemProperty twice each when desired state should be present for protocol TCP' { + $testParameters = @{ + Name = $name + Protocol = 'TCP' + ServerName = $serverNameTcp + TcpPort = $tcpPort + } + + Set-TargetResource @testParameters + + Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Test-Path -Exactly 2 -Scope It + Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName New-Item -Exactly 2 -Scope It + Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Set-ItemProperty -Exactly 2 -Scope It + } + + It 'Should call mocked functions Test-Path, New-Item and Set-ItemProperty twice each when desired state should be present for protocol Named Pipes' { + $testParameters = @{ + Name = $name + Protocol = 'NP' + ServerName = $serverNameNamedPipes + } + + Set-TargetResource @testParameters + + Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Test-Path -Exactly 2 -Scope It + Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName New-Item -Exactly 2 -Scope It + Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Set-ItemProperty -Exactly 2 -Scope It + } + + It 'Should call mocked functions Test-Path and Remove-ItemProperty twice each when desired state should be absent for 64-bit OS' { + Mock -CommandName Test-Path -MockWith { + return $true + } -ModuleName $script:DSCResourceName -Verifiable + + $testParameters = @{ + Ensure = 'Absent' + Name = $name + ServerName = $serverNameTcp + } + + Set-TargetResource @testParameters + + Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Test-Path -Exactly 2 -Scope It + Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Remove-ItemProperty -Exactly 2 -Scope It + } - Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Set-ItemProperty -Exactly 0 -Scope It - Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName New-ItemProperty -Exactly 0 -Scope It - Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Remove-ItemProperty -Exactly 2 -Scope It + } + + # Mocking 32-bit OS + Mock -CommandName Get-WmiObject -MockWith { + return New-Object Object | + Add-Member -MemberType NoteProperty -Name OSArchitecture -Value '32-bit' -PassThru -Force + } -ParameterFilter { $Class -eq 'win32_OperatingSystem' } -ModuleName $script:DSCResourceName -Verifiable + + Context 'When the system is not in the desired state for 32-bit OS using TCP' { + It 'Should call mocked functions Test-Path, New-Item and Set-ItemProperty once each when desired state should be present for protocol TCP' { + $testParameters = @{ + Name = $name + Protocol = 'TCP' + ServerName = $serverNameTcp + TcpPort = $tcpPort + } + + Set-TargetResource @testParameters + + Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Test-Path -Exactly 1 -Scope It + Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName New-Item -Exactly 1 -Scope It + Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Set-ItemProperty -Exactly 1 -Scope It + } + + It 'Should call mocked functions Test-Path, New-Item and Set-ItemProperty once each when desired state should be present for protocol Named Pipes' { + $testParameters = @{ + Name = $name + Protocol = 'NP' + ServerName = $serverNameNamedPipes + } + + Set-TargetResource @testParameters + + Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Test-Path -Exactly 1 -Scope It + Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName New-Item -Exactly 1 -Scope It + Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Set-ItemProperty -Exactly 1 -Scope It + } + + It 'Should call mocked functions Test-Path and Remove-ItemProperty once each when desired state should be absent for 32-bit OS' { + Mock -CommandName Test-Path -MockWith { + return $true + } -ModuleName $script:DSCResourceName -Verifiable + + $testParameters = @{ + Ensure = 'Absent' + Name = $name + ServerName = $serverNameNamedPipes + } + + Set-TargetResource @testParameters + + Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Test-Path -Exactly 1 -Scope It + Assert-MockCalled -ModuleName $script:DSCResourceName -CommandName Remove-ItemProperty -Exactly 1 -Scope It + } } } - #end region Set-TargetResource + #endregion Set-TargetResource #region Test-TargetResource - Describe 'Test-TargetResource' { - Mock -CommandName Test-Path -MockWith { - return $true - } -ModuleName $script:DSCResourceName + Describe "$($script:DSCResourceName)\Test-TargetResource" { + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPath -and $Name -eq $name } -MockWith { + return @{ + 'MyAlias' = 'DBMSSOCN,sqlnode.company.local,1433' + } + } -ModuleName $script:DSCResourceName -Verifiable - Mock -CommandName Get-ItemProperty -MockWith { + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPathWow6432Node -and $Name -eq $name } -MockWith { return @{ - myServerAlias = 'DBMSSOCN,localhost,1433' + 'MyAlias' = 'DBMSSOCN,sqlnode.company.local,1433' } - } -ModuleName $script:DSCResourceName + } -ModuleName $script:DSCResourceName -Verifiable + + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPath -and $Name -eq $unknownName } -MockWith { + return $null + } -ModuleName $script:DSCResourceName -Verifiable + # Mocking 64-bit OS Mock -CommandName Get-WmiObject -MockWith { + return New-Object Object | + Add-Member -MemberType NoteProperty -Name OSArchitecture -Value '64-bit' -PassThru -Force + } -ParameterFilter { $Class -eq 'win32_OperatingSystem' } -ModuleName $script:DSCResourceName -Verifiable + + Context 'When the system is in the desired state (when using TCP)' { + It 'Should return state as present ($true)' { + $testParameters = @{ + Name = $name + Protocol = 'TCP' + ServerName = $serverNameTcp + TcpPort = $tcpPort + } + + Test-TargetResource @testParameters | Should Be $true + } + } + + Context 'When the system is not in the desired state (when using TCP)' { + It 'Should return state as absent ($false)' { + $testParameters = @{ + Name = $unknownName + Protocol = 'TCP' + ServerName = $serverNameTcp + TcpPort = $tcpPort + } + + Test-TargetResource @testParameters | Should Be $false + } + } + + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPath -and $Name -eq $name } -MockWith { return @{ - Class = 'win32_OperatingSystem' - OSArchitecture = '64-bit' + 'MyAlias' = 'DBNMPNTW,\\sqlnode\PIPE\sql\query' } - } -ModuleName $script:DSCResourceName + } -ModuleName $script:DSCResourceName -Verifiable - It 'Should return $true when Test is passed as Alias thats already set'{ - Test-TargetResource -Name 'myServerAlias' -Protocol 'TCP' -ServerName localhost -TCPPort 1433 -Ensure 'Present' | Should Be $true + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPathWow6432Node -and $Name -eq $name } -MockWith { + return @{ + 'MyAlias' = 'DBNMPNTW,\\sqlnode\PIPE\sql\query' + } + } -ModuleName $script:DSCResourceName -Verifiable + + Mock -CommandName Get-ItemProperty -ParameterFilter { $Path -eq $registryPath -and $Name -eq $unknownName } -MockWith { + return $null + } -ModuleName $script:DSCResourceName -Verifiable + + Context 'When the system is in the desired state (when using Named Pipes)' { + It 'Should return state as present ($true)' { + $testParameters = @{ + Name = $name + Protocol = 'NP' + ServerName = $serverNameNamedPipes + } + + Test-TargetResource @testParameters | Should Be $true + } } - It 'Should return $false when Test is passed as Alias that is not set'{ - Test-TargetResource -Name 'myServerAlias' -Protocol 'TCP' -ServerName localhost -TCPPort 52002 -Ensure 'Present' | Should Be $false + Context 'When the system is not in the desired state (when using Named Pipes)' { + It 'Should return state as absent ($false)' { + $testParameters = @{ + Name = $unknownName + Protocol = 'NP' + ServerName = $serverNameNamedPipes + } + + Test-TargetResource @testParameters | Should Be $false + } } } - #end region Test-TargetResource + #endregion Test-TargetResource } finally {