Tests/AMPowerShellTemplate.tests.ps1

<#
Author: Flemming Rohde - flr@automize.dk
#>


#region variables
#ModuleName
$ModuleName = ($MyInvocation.MyCommand.Name).Substring(0, ($MyInvocation.MyCommand.Name).IndexOf("."))

$TestsFolderPath = Split-Path $MyInvocation.MyCommand.path

$temppath = $TestsFolderPath.Substring(0, $TestsFolderPath.LastIndexOf("\"))

$Version = $temppath.Substring($temppath.LastIndexOf("\") + 1)

Set-location $TestsFolderPath
Set-Location '..\'

#Params for Module file
$ModuleFileName = "$ModuleName.psm1"
$ModuleFileParams = @{
    name = $ModuleFileName
    path = "..\$Version\$ModuleFileName"
}

#Params for Manifest file
$ManifestFileName = "$ModuleName.psd1"
$manifestFileParams = @{
    name = $ManifestFileName
    path = "..\$Version\$ManifestFileName"
}

#Params for test file
$TestFileName = "$ModuleName.tests.ps1"
$TestFileParams = @{
    name = $TestFileName
    path = "..\$Version\Tests\$TestFileName"
}

#endregion

<#
.Synopsis
   Test a script with PowerShellScriptAnalyzer and Pester
.DESCRIPTION
   Takes a name and path as parameters and does standard PowerShellScriptAnalyzer tests with Pester
.EXAMPLE
   Test-SciptAnalyzer -Name PowerShellScript.ps1 -Path .\PowerShellScript.ps1
.FUNCTIONALITY
   Pester PowerShellScriptAnalyzer
#>

Function Test-SciptAnalyzer {
    param(
        [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String]$Name,
        [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String]$Path
    )

    $analysis = Invoke-ScriptAnalyzer -Path $Path
    $scriptAnalyzerRules = Get-ScriptAnalyzerRule

    forEach ($rule in $scriptAnalyzerRules) {
        It "Should pass $rule" {
            If ($analysis.RuleName -contains $rule) {
                $analysis | Where-Object RuleName -EQ $rule -outvariable failures | Out-Default
                $failures.Count | Should -Be 0 -Because 'It is recommended to avoid in PowerShell scripts/modules'
            }
        }
    }
}

Describe "Verify $ModuleName Files" {

    Context "Verify minimum version of Pester" {
        It "Major Version should be at least 4" {
            ((Get-Module -Name Pester).Version.Major -ge 4)| Should be $true
        }

        It "Minor Version should be at least 2" {
            ((Get-Module -Name Pester).Version.Minor -ge 2) | Should be $true
        }
    }
    
    Context "Testing $ModuleFileName against PowerShellScriptAnalyzer rules" {
        Test-SciptAnalyzer @ModuleFileParams
    }

    Context "Testing $ManifestFileName against PowerShellScriptAnalyzer rules" {
        Test-SciptAnalyzer @manifestFileParams
    } 
    
    Context "Testing $TestFileName against PowerShellScriptAnalyzer rules" {
        Test-SciptAnalyzer @TestFileParams
    }

    Context "PowerShell Manifest tests" {
               
        $ModuleManifestPath = "..\$Version\$ManifestFileName"

        $Manifest = Import-PowerShellDataFile -Path $ModuleManifestPath 
        
        it "Must have the root module fullfilled" {
            $Manifest.rootmodule | Should not benullorempty
        }

        it "Must have the author key fullfilled" {
            $Manifest.Author | should not benullorempty
        }

        it "Must have the description key fullfilled" {
            $Manifest.Description | should not benullorempty
        }

        it "Must have the company name key fullfilled" {
            $Manifest.CompanyName | should not benullorempty
        }

        it "Must have version $Version" {
            $Manifest.ModuleVersion | Should -Be $Version
        }

        it 'Must pass the Test-ModuleManifest Validation' {
            Test-ModuleManifest -Path $ModuleManifestPath | should be $true
        }    
    }

    Context "Code Unit tests" {

        It 'Import the module' {
        
            {Import-Module .\$ModuleName} | Should -Not -Throw

        }
        
        It 'Check whatif property of New-AMPowerShellModule output is null' {
        
            New-AMPowerShellModule -Name MyModule -Path C:\MyPath\ -Author 'Flemming Rohde' -CompanyName Automize -Copyright 2018 -ModuleVersion 1.0.0.0 -Description testing -WhatIf    | Should -Be $null

        }

        It 'Check whatif property of New-AMPowerShellScript output is null' {

            New-AMPowerShellScript -Name MyScript -Path C:\MyPath -WhatIf | Should -Be $null

        }

        
        It 'Test New-AMPowerShellModule' {

            Mock New-AMPowerShellModule {} 

            New-AMPowerShellModule -Name MyModule -Path C:\MyPath\ -Author 'Flemming Rohde' -CompanyName Automize -Copyright 2018 -ModuleVersion 1.0.0.0 -Description testing | Should -Be $Null
                        
        }
        

        It 'Test New-AMPowerShellScript' {
            mock New-Item {} -ModuleName $ModuleName -Verifiable

            Mock Out-File {} -ModuleName $ModuleName -Verifiable

            mock Get-Content {} -ModuleName $ModuleName -Verifiable
            
            mock Push-Location {} -ModuleName $ModuleName -Verifiable

            mock Invoke-Pester {} -ModuleName $ModuleName -Verifiable
            
            New-AMPowerShellScript -Name MyScript -Path C:\MyPath | should -Be $null
            
            Assert-VerifiableMock
        }
  
        It 'Remove the module' {
        
            {Remove-Module $ModuleName} | Should -Not -Throw 

        }

    }

    Context "Verify Codesigning of files" {
        $files = Get-ChildItem -File -Recurse | Where-Object {$PSItem.name -notlike "*.json"}

        foreach ($file in $files) {
            it "$($file.name) should be signed" {

                (Get-AuthenticodeSignature -FilePath $file.FullName).Status | Should -Be 'Valid'

            }
        }
    }

}
set-location ..\..\
# SIG # Begin signature block
# MIIcbQYJKoZIhvcNAQcCoIIcXjCCHFoCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUclgG2SAAfa3rYbs8NefIuj9Q
# e5mgghecMIIFJTCCBA2gAwIBAgIQBvr9sL154xnLx2xzI6KkMjANBgkqhkiG9w0B
# AQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD
# VQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFz
# c3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMB4XDTE2MTAxNDAwMDAwMFoXDTE5MTAy
# MzEyMDAwMFowYjELMAkGA1UEBhMCREsxEzARBgNVBAgTClN5ZGRhbm1hcmsxEDAO
# BgNVBAcTB0tvbGRpbmcxFTATBgNVBAoTDEF1dG9taXplIFAvUzEVMBMGA1UEAxMM
# QXV0b21pemUgUC9TMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw9ot
# S4zzE1kP2SFLvYVXeM16FNJOMaESNYXUuE9rrzXUDyBpLA9EiCvOvnAaii1XvFfg
# 6OJpCppnNzrJCZ3rTdHm7Lf/P7LCQUk3Pc6xI5jHcLKUaINFo529+2yVqNPzqMJ/
# OgT2nxQiU6BaEwauK5xEbRwF/Fu3jZMvC7+1TM3MjO6aGnoey0kYaHrXdY+lqTlp
# QJ287vrYrJIsYZfrlYkEQTJe5wMx8QL6KvkMfXxeFoUVz9SIS9CPsYhHRYlEAWhD
# hgV+x/8l3Kpiu8lrsfpqQndS/rfS46sIhtmI2ppc2kWqvcXfAvxzVF/3P5p0JbbF
# hPBrjKE6V6C/nhKvHwIDAQABo4IBxTCCAcEwHwYDVR0jBBgwFoAUWsS5eyoKo6Xq
# cQPAYPkt9mV1DlgwHQYDVR0OBBYEFLZGaqf5X3DRHeeZ1xZYk5xr4MKDMA4GA1Ud
# DwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzB3BgNVHR8EcDBuMDWgM6Ax
# hi9odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLWNzLWcxLmNy
# bDA1oDOgMYYvaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1j
# cy1nMS5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAwEwKjAoBggrBgEFBQcCARYc
# aHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBBAEwgYQGCCsGAQUF
# BwEBBHgwdjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tME4G
# CCsGAQUFBzAChkJodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRT
# SEEyQXNzdXJlZElEQ29kZVNpZ25pbmdDQS5jcnQwDAYDVR0TAQH/BAIwADANBgkq
# hkiG9w0BAQsFAAOCAQEANMxgqONAb/uyja3uk0w1n/9pNE82rs8Mt6HrB4N6Xe2Y
# EHD01OXq97y1wikMG/G5rD8N16S9LtQpI3YqmjukuKr96Rm8oPapw13hTyYYPouV
# Wkxm/jzEmvp6rkLXR4cX4+VRHbepyZRv3ATzH/3B9zu/wM54AmNShgpSobYC6YR1
# RdeaDI9kbQbv4x0qlkAGTiF4O5bzX3EQyOgx8LTF1WuKVQySTNukrC36XaCZ1TgG
# 1lG5M3/AV0Aw6f6RvzPZqwAypj2/ncuRJ19ElsMmXd7f3CMO/gJKV2yhr90yS0ik
# DHb1vm6mdP1QnBe/em2i40GF4tvCOKZAGm6+YLdruDCCBTAwggQYoAMCAQICEAQJ
# GBtf1btmdVNDtW+VUAgwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCVVMxFTAT
# BgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEk
# MCIGA1UEAxMbRGlnaUNlcnQgQXNzdXJlZCBJRCBSb290IENBMB4XDTEzMTAyMjEy
# MDAwMFoXDTI4MTAyMjEyMDAwMFowcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERp
# Z2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMo
# RGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIENvZGUgU2lnbmluZyBDQTCCASIwDQYJ
# KoZIhvcNAQEBBQADggEPADCCAQoCggEBAPjTsxx/DhGvZ3cH0wsxSRnP0PtFmbE6
# 20T1f+Wondsy13Hqdp0FLreP+pJDwKX5idQ3Gde2qvCchqXYJawOeSg6funRZ9PG
# +yknx9N7I5TkkSOWkHeC+aGEI2YSVDNQdLEoJrskacLCUvIUZ4qJRdQtoaPpiCwg
# la4cSocI3wz14k1gGL6qxLKucDFmM3E+rHCiq85/6XzLkqHlOzEcz+ryCuRXu0q1
# 6XTmK/5sy350OTYNkO/ktU6kqepqCquE86xnTrXE94zRICUj6whkPlKWwfIPEvTF
# jg/BougsUfdzvL2FsWKDc0GCB+Q4i2pzINAPZHM8np+mM6n9Gd8lk9ECAwEAAaOC
# Ac0wggHJMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMBMGA1Ud
# JQQMMAoGCCsGAQUFBwMDMHkGCCsGAQUFBwEBBG0wazAkBggrBgEFBQcwAYYYaHR0
# cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAChjdodHRwOi8vY2FjZXJ0
# cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3J0MIGBBgNV
# HR8EejB4MDqgOKA2hjRodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRB
# c3N1cmVkSURSb290Q0EuY3JsMDqgOKA2hjRodHRwOi8vY3JsMy5kaWdpY2VydC5j
# b20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsME8GA1UdIARIMEYwOAYKYIZI
# AYb9bAACBDAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20v
# Q1BTMAoGCGCGSAGG/WwDMB0GA1UdDgQWBBRaxLl7KgqjpepxA8Bg+S32ZXUOWDAf
# BgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkqhkiG9w0BAQsFAAOC
# AQEAPuwNWiSz8yLRFcgsfCUpdqgdXRwtOhrE7zBh134LYP3DPQ/Er4v97yrfIFU3
# sOH20ZJ1D1G0bqWOWuJeJIFOEKTuP3GOYw4TS63XX0R58zYUBor3nEZOXP+QsRsH
# DpEV+7qvtVHCjSSuJMbHJyqhKSgaOnEoAjwukaPAJRHinBRHoXpoaK+bp1wgXNlx
# sQyPu6j4xRJon89Ay0BEpRPw5mQMJQhCMrI2iiQC/i9yfhzXSUWW6Fkd6fp0ZGuy
# 62ZD2rOwjNXpDd32ASDOmTFjPQgaGLOBm0/GkxAG/AeB+ova+YJJ92JuoVP6EpQY
# hS6SkepobEQysmah5xikmmRR7zCCBmowggVSoAMCAQICEAMBmgI6/1ixa9bV6uYX
# 8GYwDQYJKoZIhvcNAQEFBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lD
# ZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGln
# aUNlcnQgQXNzdXJlZCBJRCBDQS0xMB4XDTE0MTAyMjAwMDAwMFoXDTI0MTAyMjAw
# MDAwMFowRzELMAkGA1UEBhMCVVMxETAPBgNVBAoTCERpZ2lDZXJ0MSUwIwYDVQQD
# ExxEaWdpQ2VydCBUaW1lc3RhbXAgUmVzcG9uZGVyMIIBIjANBgkqhkiG9w0BAQEF
# AAOCAQ8AMIIBCgKCAQEAo2Rd/Hyz4II14OD2xirmSXU7zG7gU6mfH2RZ5nxrf2uM
# nVX4kuOe1VpjWwJJUNmDzm9m7t3LhelfpfnUh3SIRDsZyeX1kZ/GFDmsJOqoSyyR
# icxeKPRktlC39RKzc5YKZ6O+YZ+u8/0SeHUOplsU/UUjjoZEVX0YhgWMVYd5SEb3
# yg6Np95OX+Koti1ZAmGIYXIYaLm4fO7m5zQvMXeBMB+7NgGN7yfj95rwTDFkjePr
# +hmHqH7P7IwMNlt6wXq4eMfJBi5GEMiN6ARg27xzdPpO2P6qQPGyznBGg+naQKFZ
# OtkVCVeZVjCT88lhzNAIzGvsYkKRrALA76TwiRGPdwIDAQABo4IDNTCCAzEwDgYD
# VR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUH
# AwgwggG/BgNVHSAEggG2MIIBsjCCAaEGCWCGSAGG/WwHATCCAZIwKAYIKwYBBQUH
# AgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwggFkBggrBgEFBQcCAjCC
# AVYeggFSAEEAbgB5ACAAdQBzAGUAIABvAGYAIAB0AGgAaQBzACAAQwBlAHIAdABp
# AGYAaQBjAGEAdABlACAAYwBvAG4AcwB0AGkAdAB1AHQAZQBzACAAYQBjAGMAZQBw
# AHQAYQBuAGMAZQAgAG8AZgAgAHQAaABlACAARABpAGcAaQBDAGUAcgB0ACAAQwBQ
# AC8AQwBQAFMAIABhAG4AZAAgAHQAaABlACAAUgBlAGwAeQBpAG4AZwAgAFAAYQBy
# AHQAeQAgAEEAZwByAGUAZQBtAGUAbgB0ACAAdwBoAGkAYwBoACAAbABpAG0AaQB0
# ACAAbABpAGEAYgBpAGwAaQB0AHkAIABhAG4AZAAgAGEAcgBlACAAaQBuAGMAbwBy
# AHAAbwByAGEAdABlAGQAIABoAGUAcgBlAGkAbgAgAGIAeQAgAHIAZQBmAGUAcgBl
# AG4AYwBlAC4wCwYJYIZIAYb9bAMVMB8GA1UdIwQYMBaAFBUAEisTmLKZB+0e36K+
# Vw0rZwLNMB0GA1UdDgQWBBRhWk0ktkkynUoqeRqDS/QeicHKfTB9BgNVHR8EdjB0
# MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVk
# SURDQS0xLmNybDA4oDagNIYyaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lD
# ZXJ0QXNzdXJlZElEQ0EtMS5jcmwwdwYIKwYBBQUHAQEEazBpMCQGCCsGAQUFBzAB
# hhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQQYIKwYBBQUHMAKGNWh0dHA6Ly9j
# YWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRENBLTEuY3J0MA0G
# CSqGSIb3DQEBBQUAA4IBAQCdJX4bM02yJoFcm4bOIyAPgIfliP//sdRqLDHtOhcZ
# cRfNqRu8WhY5AJ3jbITkWkD73gYBjDf6m7GdJH7+IKRXrVu3mrBgJuppVyFdNC8f
# cbCDlBkFazWQEKB7l8f2P+fiEUGmvWLZ8Cc9OB0obzpSCfDscGLTYkuw4HOmksDT
# jjHYL+NtFxMG7uQDthSr849Dp3GdId0UyhVdkkHa+Q+B0Zl0DSbEDn8btfWg8cZ3
# BigV6diT5VUW8LsKqxzbXEgnZsijiwoc5ZXarsQuWaBh3drzbaJh6YoLbewSGL33
# VVRAA5Ira8JRwgpIr7DUbuD0FAo6G+OPPcqvao173NhEMIIGzTCCBbWgAwIBAgIQ
# Bv35A5YDreoACus/J7u6GzANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJVUzEV
# MBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29t
# MSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEw
# MDAwMDAwWhcNMjExMTEwMDAwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMM
# RGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQD
# ExhEaWdpQ2VydCBBc3N1cmVkIElEIENBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IB
# DwAwggEKAoIBAQDogi2Z+crCQpWlgHNAcNKeVlRcqcTSQQaPyTP8TUWRXIGf7Syc
# +BZZ3561JBXCmLm0d0ncicQK2q/LXmvtrbBxMevPOkAMRk2T7It6NggDqww0/hhJ
# gv7HxzFIgHweog+SDlDJxofrNj/YMMP/pvf7os1vcyP+rFYFkPAyIRaJxnCI+QWX
# faPHQ90C6Ds97bFBo+0/vtuVSMTuHrPyvAwrmdDGXRJCgeGDboJzPyZLFJCuWWYK
# xI2+0s4Grq2Eb0iEm09AufFM8q+Y+/bOQF1c9qjxL6/siSLyaxhlscFzrdfx2M8e
# CnRcQrhofrfVdwonVnwPYqQ/MhRglf0HBKIJAgMBAAGjggN6MIIDdjAOBgNVHQ8B
# Af8EBAMCAYYwOwYDVR0lBDQwMgYIKwYBBQUHAwEGCCsGAQUFBwMCBggrBgEFBQcD
# AwYIKwYBBQUHAwQGCCsGAQUFBwMIMIIB0gYDVR0gBIIByTCCAcUwggG0BgpghkgB
# hv1sAAEEMIIBpDA6BggrBgEFBQcCARYuaHR0cDovL3d3dy5kaWdpY2VydC5jb20v
# c3NsLWNwcy1yZXBvc2l0b3J5Lmh0bTCCAWQGCCsGAQUFBwICMIIBVh6CAVIAQQBu
# AHkAIAB1AHMAZQAgAG8AZgAgAHQAaABpAHMAIABDAGUAcgB0AGkAZgBpAGMAYQB0
# AGUAIABjAG8AbgBzAHQAaQB0AHUAdABlAHMAIABhAGMAYwBlAHAAdABhAG4AYwBl
# ACAAbwBmACAAdABoAGUAIABEAGkAZwBpAEMAZQByAHQAIABDAFAALwBDAFAAUwAg
# AGEAbgBkACAAdABoAGUAIABSAGUAbAB5AGkAbgBnACAAUABhAHIAdAB5ACAAQQBn
# AHIAZQBlAG0AZQBuAHQAIAB3AGgAaQBjAGgAIABsAGkAbQBpAHQAIABsAGkAYQBi
# AGkAbABpAHQAeQAgAGEAbgBkACAAYQByAGUAIABpAG4AYwBvAHIAcABvAHIAYQB0
# AGUAZAAgAGgAZQByAGUAaQBuACAAYgB5ACAAcgBlAGYAZQByAGUAbgBjAGUALjAL
# BglghkgBhv1sAxUwEgYDVR0TAQH/BAgwBgEB/wIBADB5BggrBgEFBQcBAQRtMGsw
# JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEFBQcw
# AoY3aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElE
# Um9vdENBLmNydDCBgQYDVR0fBHoweDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNl
# cnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDA6oDigNoY0aHR0cDov
# L2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDAd
# BgNVHQ4EFgQUFQASKxOYspkH7R7for5XDStnAs0wHwYDVR0jBBgwFoAUReuir/SS
# y4IxLVGLp6chnfNtyA8wDQYJKoZIhvcNAQEFBQADggEBAEZQPsm3KCSnOB22Wymv
# Us9S6TFHq1Zce9UNC0Gz7+x1H3Q48rJcYaKclcNQ5IK5I9G6OoZyrTh4rHVdFxc0
# ckeFlFbR67s2hHfMJKXzBBlVqefj56tizfuLLZDCwNK1lL1eT7EF0g49GqkUW6aG
# MWKoqDPkmzmnxPXOHXh2lCVz5Cqrz5x2S+1fwksW5EtwTACJHvzFebxMElf+X+Ee
# vAJdqP77BzhPDcZdkbkPZ0XN1oPt55INjbFpjE/7WeAjD9KqrgB87pxCDs+R1ye3
# Fu4Pw718CqDuLAhVhSK46xgaTfwqIa1JMYNHlXdx3LEbS0scEJx3FMGdTy9alQgp
# ECYxggQ7MIIENwIBATCBhjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNl
# cnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdp
# Q2VydCBTSEEyIEFzc3VyZWQgSUQgQ29kZSBTaWduaW5nIENBAhAG+v2wvXnjGcvH
# bHMjoqQyMAkGBSsOAwIaBQCgeDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkG
# CSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEE
# AYI3AgEVMCMGCSqGSIb3DQEJBDEWBBTq+0Tk7CGA23T18ugdGaW5KtiZrDANBgkq
# hkiG9w0BAQEFAASCAQCdSfDh6gtf75I8uPPrShDDU3hf6fJJfZZIWrvzyTW/pkgu
# n897/8iwV5z1O7erp82gk3xjb89Y2MXJrx9nrnJUDz2b7hTERv97hYHb4wStEaPd
# 3Qhho3LRL5otDDuN83XXkPKBjFrd87XLuo2SQ//SP3euhOn+4oYksXwVj/Nmv60s
# 3+fzQen15KlV5TzWJlsbcnggMMnfTxDSxE9EBBb+R2wknMFzoY6/8vLQi3DFT8Fh
# lXmxsYPUkg8K8Fqm8tXxJgaQpCVh/wBNMs2pVjK9Gfyc4PGQU53tTEamjMw8uO57
# v5GMjCQviungqY6529jfK6ZmYwm/aas/NvC8bQWgoYICDzCCAgsGCSqGSIb3DQEJ
# BjGCAfwwggH4AgEBMHYwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0
# IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNl
# cnQgQXNzdXJlZCBJRCBDQS0xAhADAZoCOv9YsWvW1ermF/BmMAkGBSsOAwIaBQCg
# XTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xODA0
# MTkxMDE0NTJaMCMGCSqGSIb3DQEJBDEWBBQwxh0TNMVpo+/cK3VpydU6sgJBnTAN
# BgkqhkiG9w0BAQEFAASCAQBc9X+6DhNctDeLIPDxp0BeZjOwFqjcAuT4wvZ5nO9H
# byCBiPkUI7PqO6CyVHxisDYi9pBMuF5C7Uv8erVcxpAUf0dKgkqNA6ZtMFVlq0nC
# 5FeQIfoTZzRUURYgFKPAdHTVNaCy1w0YbfZ78jLSsWNwTJ8tAkA3sUtDOPEemFlx
# Ia27wkAHuEXJD34QmulHuCJ5m2FUnXLDEQI09qDWH1E62TRrYu4uQQu2945UHhZj
# CX24QbLhuq52ypMeRPahdew/6J67S4gC8qSSRAkibzCrPidCntVSAgi+AndPlcjX
# M22M92p4IfqQK38AWLUb49QmK1IPjFmueegeiXt0trYd
# SIG # End signature block