Tests/cOctopusServer.Tests.ps1

#requires -Version 4.0
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '')] # these are tests, not anything that needs to be secure
param()

$moduleName = Split-Path ($PSCommandPath -replace '\.Tests\.ps1$', '') -Leaf
$modulePath = Resolve-Path "$PSCommandPath/../../DSCResources/$moduleName/$moduleName.psm1"
$module = $null

try
{
    $prefix = [guid]::NewGuid().Guid -replace '-'

    $module = Import-Module $modulePath -Prefix $prefix -PassThru -ErrorAction Stop

    InModuleScope $module.Name {

        # Get-Service is not available on mac/unix systems - fake it
        $getServiceCommand = Get-Command "Get-Service" -ErrorAction SilentlyContinue
        if ($null -eq $getServiceCommand) {
            function Get-Service {}
        }

        function Get-DesiredConfiguration {
            $pass = ConvertTo-SecureString "S3cur3P4ssphraseHere!" -AsPlainText -Force
            $cred = New-Object System.Management.Automation.PSCredential ("Admin", $pass)

            [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]
            $desiredConfiguration = @{
                 Name                   = 'Stub'
                 Ensure                 = 'Present'
                 State                  = 'Started'
                 WebListenPrefix        = "http://localhost:80"
                 SqlDbConnectionString  = "conn-string"
                 OctopusAdminCredential = $cred
            }
            return $desiredConfiguration
        }

        Describe 'cOctopusServer' {
            BeforeEach {

            }

            [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]
            $mockConfig = [pscustomobject] @{
                OctopusStorageExternalDatabaseConnectionString         = 'StubConnectionString'
                OctopusWebPortalListenPrefixes                         = "https://octopus.example.com,http://localhost"
            }
            Mock Import-ServerConfig { return $mockConfig }

            Context 'Get-TargetResource' {
                Mock Get-ItemProperty { return @{ InstallLocation = "c:\Octopus\Octopus" }}
                Mock Get-Service { return @{ Status = "Running" }}

                It 'Returns the proper data' {
                    $desiredConfiguration = Get-DesiredConfiguration
                    $config = Get-TargetResource @desiredConfiguration

                    $config.GetType()                  | Should Be ([hashtable])
                    $config['Name']                    | Should Be 'Stub'
                    $config['Ensure']                  | Should Be 'Present'
                    $config['State']                   | Should Be 'Started'
                }
            }

            Context 'When reg key exists and service exists and service started' {
                Mock Get-ItemProperty { return @{ InstallLocation = "c:\Octopus\Octopus" }}
                Mock Get-Service { return @{ Status = "Running" }}
                $desiredConfiguration = Get-DesiredConfiguration
                $config = Get-TargetResource @desiredConfiguration

                It 'Should have Ensure=Present' {
                    $config['Ensure']                  | Should Be 'Present'
                }
                It 'Should have State=Started' {
                    $config['State']                   | Should Be 'Started'
                }
            }

            Context 'When reg key exists and service exists and service stopped' {
                Mock Get-ItemProperty { return @{ InstallLocation = "c:\Octopus\Octopus" }}
                Mock Get-Service { return @{ Status = "Stopped" }}
                $desiredConfiguration = Get-DesiredConfiguration
                $config = Get-TargetResource @desiredConfiguration

                It 'Should have Ensure=Present' {
                    $config['Ensure']                  | Should Be 'Present'
                }
                It 'Should have State=Stopped' {
                    $config['State']                   | Should Be 'Stopped'
                }
            }

            Context 'When reg key exists and service does not exist' {
                Mock Get-ItemProperty { return @{ InstallLocation = "c:\Octopus\Octopus" }}
                Mock Get-Service { return $null }
                $desiredConfiguration = Get-DesiredConfiguration
                $config = Get-TargetResource @desiredConfiguration

                It 'Should have Ensure=Present' {
                    $config['Ensure']                  | Should Be 'Present'
                }
                It 'Should have State=Installed' {
                    $config['State']                   | Should Be 'Installed'
                }
            }

            Context 'When reg key does not exist and service does not exist' {
                Mock Get-ItemProperty { return $null }
                Mock Get-Service { return $null }
                $desiredConfiguration = Get-DesiredConfiguration
                $config = Get-TargetResource @desiredConfiguration

                It 'Should have Ensure=Absent' {
                    $config['Ensure']                  | Should Be 'Absent'
                }
                It 'Should have State=Stopped' {
                    $config['State']                   | Should Be 'Stopped'
                }
            }

            Context 'When reg key does not exist and service started' {
                Mock Get-ItemProperty { return $null }
                Mock Get-Service { return @{ Status = "Running" } }
                $desiredConfiguration = Get-DesiredConfiguration
                $config = Get-TargetResource @desiredConfiguration

                It 'Should have Ensure=Present' {
                    $config['Ensure']                  | Should Be 'Present'
                }
                It 'Should have State=Started' {
                    $config['State']                   | Should Be 'Started'
                }
            }

            Context 'When reg key does not exist and service stopped' {
                Mock Get-ItemProperty { return $null }
                Mock Get-Service { return @{ Status = "Stopped" } }
                $desiredConfiguration = Get-DesiredConfiguration
                $config = Get-TargetResource @desiredConfiguration

                It 'Should have Ensure=Present' {
                    $config['Ensure']                  | Should Be 'Present'
                }
                It 'Should have State=Stopped' {
                    $config['State']                   | Should Be 'Stopped'
                }
            }

            # Context 'Test-TargetResource' {
            # $response = @{ Ensure="Absent"; State="Stopped" }
            # Mock Get-TargetResource { return $response }

            # It 'Returns True when Ensure is set to Absent and Instance does not exist' {
            # $desiredConfiguration['Ensure'] = 'Absent'
            # $desiredConfiguration['State'] = 'Stopped'
            # $response['Ensure'] = 'Absent'
            # $response['State'] = 'Stopped'

            # Test-TargetResource @desiredConfiguration | Should Be $true
            # }

            # It 'Returns True when Ensure is set to Present and Instance exists' {
            # $desiredConfiguration['Ensure'] = 'Present'
            # $desiredConfiguration['State'] = 'Started'
            # $response['Ensure'] = 'Present'
            # $response['State'] = 'Started'

            # Test-TargetResource @desiredConfiguration | Should Be $true
            # }
            # }

            # Context 'Set-TargetResource' {
            # #todo: more tests
            # It 'Throws an exception if .net 4.5.1 or above is not installed (no .net reg key found)' {
            # Mock Install-Msi {}
            # Mock Get-RegistryValue { return "" }
            # { Set-TargetResource @desiredConfiguration } | Should throw "Octopus Server requires .NET 4.5.1. Please install it before attempting to install Octopus Server."
            # }

            # It 'Throws an exception if .net 4.5.1 or above is not installed (only .net 4.5.0 installed)' {
            # Mock Install-Msi {}
            # Mock Get-RegistryValue { return "378389" }
            # { Set-TargetResource @desiredConfiguration } | Should throw "Octopus Server requires .NET 4.5.1. Please install it before attempting to install Octopus Server."
            # }
            # }

            # function Get-CurrentConfiguration ([string] $testName) {
            # & (Resolve-Path "$PSCommandPath/../../Tests/OctopusServerExeInvocationFiles/$testName/CurrentState.ps1")
            # }

            # function Get-RequestedConfiguration ([string] $testName) {
            # & (Resolve-Path "$PSCommandPath/../../Tests/OctopusServerExeInvocationFiles/$testName/RequestedState.ps1")
            # }

            # function Assert-ExpectedResult ([string] $testName) {
            # # todo: test order of execution here
            # $invocations = & (Resolve-Path "$PSCommandPath/../../Tests/OctopusServerExeInvocationFiles/$testName/ExpectedResult.ps1")
            # it "Should call octopus.server.exe $($invocations.count) times" {
            # Assert-MockCalled -CommandName 'Invoke-OctopusServerCommand' -Times $invocations.Count -Exactly
            # }
            # foreach($line in $invocations) {
            # It "Should call octopus.server.exe with args '$line'" {
            # Assert-MockCalled -CommandName 'Invoke-OctopusServerCommand' -Times 1 -Exactly -ParameterFilter { ($arguments -join ' ') -eq $line }
            # }
            # }
            # }

            # function Get-TempFolder {
            # if ("$($env:TmpDir)" -ne "") {
            # return $env:TmpDir
            # } else {
            # return $env:Temp
            # }
            # }

            # Context "New instance" {
            # Mock Invoke-OctopusServerCommand #{write-host $args}
            # Mock Get-TargetResource { return Get-CurrentConfiguration "NewInstance" }
            # Mock Get-RegistryValue { return "478389" } # checking .net 4.5
            # Mock Install-MSI {}
            # Mock Update-InstallState {}
            # Mock Test-OctopusDeployServerResponding { return $true }
            # Mock Test-OctopusVersionNewerThan { return $true } # just assume we're the most recent version
            # Mock ConvertFrom-SecureString { return "" } # mock this, as its not available on mac/linux

            # $params = Get-RequestedConfiguration "NewInstance"
            # Set-TargetResource @params

            # Assert-ExpectedResult "NewInstance"
            # it "Should download the MSI" {
            # Assert-MockCalled Install-MSI
            # }
            # }

            # Context "When MasterKey is supplied on new instance" {
            # Mock Invoke-OctopusServerCommand #{write-host $args}
            # Mock Get-TargetResource { return Get-CurrentConfiguration "MasterKeySupplied" }
            # Mock Get-RegistryValue { return "478389" } # checking .net 4.5
            # Mock Install-MSI {}
            # Mock Update-InstallState {}
            # Mock Test-OctopusDeployServerResponding { return $true }
            # Mock Test-OctopusVersionNewerThan { return $true } # just assume we're the most recent version
            # Mock ConvertFrom-SecureString { return "" } # mock this, as its not available on mac/linux

            # $params = Get-RequestedConfiguration "MasterKeySupplied"

            # Set-TargetResource @params

            # it "Should download the MSI" {
            # Assert-MockCalled Install-MSI
            # }
            # Assert-ExpectedResult "MasterKeySupplied"
            # }

            # Context "When uninstalling running instance" {
            # Mock Invoke-OctopusServerCommand #{ param ($arguments) write-host $arguments}
            # Mock Get-TargetResource { return Get-CurrentConfiguration "UninstallingRunningInstance" }
            # Mock Install-MSI {}
            # Mock Get-ExistingOctopusServices { return @() }
            # Mock Get-LogDirectory { return Get-TempFolder }
            # Mock Test-Path -ParameterFilter { $path -eq "$($env:SystemDrive)\Octopus\Octopus-x64.msi" } { return $true }
            # Mock Start-Process { return @{ ExitCode = 0} }

            # $params = Get-RequestedConfiguration "UninstallingRunningInstance"
            # Set-TargetResource @params

            # it "Should not download the MSI" {
            # Assert-MockCalled Install-MSI -Times 0 -Exactly
            # }
            # it "Should uninstall the MSI" {
            # Assert-MockCalled Start-Process -Times 1 -Exactly -ParameterFilter { $FilePath -eq "msiexec.exe" -and $ArgumentList -eq "/x $($env:SystemDrive)\Octopus\Octopus-x64.msi /quiet /l*v $(Get-TempFolder)\Octopus-x64.msi.uninstall.log"}
            # }
            # Assert-ExpectedResult "UninstallingRunningInstance"
            # }

            # Context "Run-on-server user - new install" {
            # Mock Invoke-OctopusServerCommand #{ param ($arguments) write-host $arguments}
            # Mock Get-TargetResource { return Get-CurrentConfiguration "NewInstallWithBuiltInWorker" }
            # Mock Get-RegistryValue { return "478389" } # checking .net 4.5
            # Mock Install-MSI {}
            # Mock Update-InstallState {}
            # Mock Test-OctopusDeployServerResponding { return $true }
            # Mock Test-OctopusVersionNewerThan { return $true }
            # Mock ConvertFrom-SecureString { return "" } # mock this, as its not available on mac/linux
            # Mock Test-IsOctopusUpgrade { return $false } # we're installing new

            # $params = Get-RequestedConfiguration "NewInstallWithBuiltInWorker"
            # Set-TargetResource @params

            # it "Should download the MSI" {
            # Assert-MockCalled Install-MSI
            # }
            # Assert-ExpectedResult "NewInstallWithBuiltInWorker"
            # }

            # Context "Run-on-server user - existing install" {
            # Mock Invoke-OctopusServerCommand #{ param ($arguments) write-host $arguments}
            # Mock Get-TargetResource { return Get-CurrentConfiguration "EnableBuiltInWorkerOnExistingInstance" }
            # Mock Get-RegistryValue { return "478389" } # checking .net 4.5
            # Mock Install-MSI {}
            # Mock Update-InstallState {}
            # Mock Test-OctopusDeployServerResponding { return $true }
            # Mock Test-OctopusVersionNewerThan { return $true }
            # Mock ConvertFrom-SecureString { return "" } # mock this, as its not available on mac/linux

            # $params = Get-RequestedConfiguration "EnableBuiltInWorkerOnExistingInstance"
            # Set-TargetResource @params

            # it "Should not download the MSI" {
            # Assert-MockCalled Install-MSI -Times 0 -Exactly
            # }
            # Assert-ExpectedResult "EnableBuiltInWorkerOnExistingInstance"
            # }

            # Context "Upgrade" {
            # Mock Invoke-OctopusServerCommand #{ param ($arguments) write-host $arguments}
            # Mock Get-TargetResource { return Get-CurrentConfiguration "UpgradeExistingInstance" }
            # Mock Get-RegistryValue { return "478389" } # checking .net 4.5
            # Mock Install-MSI {}
            # Mock Update-InstallState {}
            # Mock Test-OctopusDeployServerResponding { return $true }
            # Mock Test-OctopusVersionNewerThan { return $true }
            # Mock ConvertFrom-SecureString { return "" } # mock this, as its not available on mac/linux

            # $params = Get-RequestedConfiguration "UpgradeExistingInstance"
            # Set-TargetResource @params

            # it "Should download the MSI" {
            # Assert-MockCalled Install-MSI
            # }
            # Assert-ExpectedResult "UpgradeExistingInstance"
            # }
        }
    }
}
finally
{
    if ($module) {
        Remove-Module -ModuleInfo $module
    }
}