Migrates to Pester5+ tests (#59)

#### 📖 Summary

- update Pester tests to Pester5+ compatiple layout
- switch to dotnet base imaged
  - dotnet binary required for publishung powershell modules (Publish-Module)

#### 📑 Test Plan

> 💡 Select your test plan for the code changes.

- [x] Tested via Drone.io pipeline
- [ ] Custom test
- [ ] No test plan

##### Details / Justification

<!-- Add your test details or justification for missing tests here. -->

#### 📚 Additional Notes

<!-- A place for additional detail notes. -->

Co-authored-by: OCram85 <marco.blessing@googlemail.com>
Reviewed-on: OCram85/PSCredentialStore#59
This commit is contained in:
OCram85 2022-07-14 13:37:12 +02:00
parent e3404666d4
commit d4b00a5308
31 changed files with 636 additions and 333 deletions

View File

@ -1,7 +1,7 @@
--- ---
kind: pipeline kind: pipeline
type: docker type: docker
name: Linux_PWSH7_Build name: PWSH_LTS_7.2_Ubuntu-focal
platform: platform:
os: linux os: linux
@ -9,7 +9,7 @@ platform:
steps: steps:
- name: Environments - name: Environments
image: mcr.microsoft.com/powershell:latest image: mcr.microsoft.com/powershell:lts-7.2-ubuntu-focal
commands: commands:
- | - |
pwsh -NonInteractive -c "& { pwsh -NonInteractive -c "& {
@ -18,29 +18,47 @@ steps:
}" }"
- name: LintTests - name: LintTests
image: mcr.microsoft.com/powershell:latest image: mcr.microsoft.com/powershell:lts-7.2-ubuntu-focal
failure: ignore
commands: commands:
- | - |
pwsh -NonInteractive -c "& { pwsh -NonInteractive -c "& {
Import-Module './tools/DroneIO.psm1'; Import-Module './tools/DroneIO.psm1';
Invoke-InstallDependencies; Invoke-InstallDependencies;
Invoke-Linter Invoke-Linter -ErrorAction 'Stop'
}" }"
- name: UnitTests - name: UnitTests
image: mcr.microsoft.com/powershell:latest image: mcr.microsoft.com/powershell:lts-7.2-ubuntu-focal
failure: ignore
commands: commands:
- | - |
pwsh -NonInteractive -c "& { pwsh -NonInteractive -c "& {
Import-Module './tools/DroneIO.psm1'; Import-Module './tools/DroneIO.psm1';
Invoke-InstallDependencies; Invoke-InstallDependencies;
Invoke-UnitTest -Verbosity 'Detailed' Invoke-UnitTest -Verbosity 'Normal' -ExcludeTag @( 'Integration', 'Disabled') -ErrorAction 'Stop'
}" }"
- name: coverage # Disable Codecov for self hosted git
image: plugins/codecov #- name: Coverage
settings: # image: plugins/codecov
token: # settings:
from_secret: CodeCovToken # token:
files: # from_secret: CodeCovToken
- coverage.xml # files:
# - coverage.xml
# depends_on:
# - UnitTests
- name: SetPipelineState
image: mcr.microsoft.com/powershell:lts-7.2-ubuntu-focal
commands:
- |
pwsh -NonInteractive -c "& {
Import-Module './tools/DroneIO.psm1';
Invoke-BuildState -ErrorAction 'Stop'
}"
depends_on:
- LintTests
- UnitTests
#- Coverage

3
.gitignore vendored
View File

@ -16,3 +16,6 @@ data/*.csv
# Ignore Unit Test result files # Ignore Unit Test result files
coverage.xml coverage.xml
testResults.xml testResults.xml
# Optional build state file
STATE.xml

View File

@ -0,0 +1,20 @@
BeforeAll {
$ManifestFile = (Get-Item -Path "./src/*.psd1").FullName
Import-Module $ManifestFile -Force
}
Describe "New-CSCertAttribute" {
Context "Basis Tests" -Tag 'Unit' {
It "Should not throw" {
$AttribParams = @{
Country = 'DE'
State = 'BW'
City = 'KA'
Organization = 'IT'
OrganizationalUnitName = 'foo'
CommonName = 'MyCert'
}
{ New-CSCertAttribute @AttribParams } | Should -Not -Throw
}
}
}

View File

@ -0,0 +1,33 @@
BeforeAll {
$ManifestFile = (Get-Item -Path "./src/*.psd1").FullName
Import-Module $ManifestFile -Force
$PrivateFunctions = (Get-ChildItem -Path "./src/Private/*.ps1" | Where-Object {
$_.BaseName -notmatch '.Tests'
}
).FullName
foreach ( $func in $PrivateFunctions) {
. $func
}
}
Describe "New-CSCertificate" {
Context "Basic Tests" -Tag 'Unit' {
It "Should not throw" {
$attribs = @{
Country = 'DE'
State = 'BW'
City = 'KA'
Organization = 'IT'
OrganizationalUnitName = 'foo'
CommonName = 'MyCert'
}
$CertAttribs = @{
CRTAttribute = New-CSCertAttribute @attribs
KeyName = Join-Path -Path (Get-TempDir) -ChildPath '/foo.key'
CertName = Join-Path -Path (Get-TempDir) -ChildPath '/cert.pfx'
}
{ New-CSCertificate @CertAttribs } | Should -Not -Throw
}
}
}

View File

@ -11,22 +11,28 @@
<ListEntry> <ListEntry>
<ListItems> <ListItems>
<ListItem> <ListItem>
<PropertyName>Country</PropertyName> <Label>Country</Label>
<ScriptBlock>$_.Subject.Country</ScriptBlock>
</ListItem> </ListItem>
<ListItem> <ListItem>
<PropertyName>State</PropertyName> <Label>State</Label>
<ScriptBlock>$_.Subject.State</ScriptBlock>
</ListItem> </ListItem>
<ListItem> <ListItem>
<PropertyName>City</PropertyName> <Label>City</Label>
<ScriptBlock>$_.Subject.City</ScriptBlock>
</ListItem> </ListItem>
<ListItem> <ListItem>
<PropertyName>Organization</PropertyName> <Label>Organization</Label>
<ScriptBlock>$_.Subject.Organization</ScriptBlock>
</ListItem> </ListItem>
<ListItem> <ListItem>
<PropertyName>OrganizationalUnitName</PropertyName> <Label>OrganizationalUnitName</Label>
<ScriptBlock>$_.Subject.OrganizationalUnitName</ScriptBlock>
</ListItem> </ListItem>
<ListItem> <ListItem>
<PropertyName>CommonName</PropertyName> <Label>CommonName</Label>
<ScriptBlock>$_.Subject.CommonName</ScriptBlock>
</ListItem> </ListItem>
</ListItems> </ListItems>
</ListEntry> </ListEntry>

View File

@ -1,6 +1,31 @@
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSAvoidUsingConvertToSecureStringWithPlainText',
'',
Justification = 'just used in pester tests.'
)]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSProvideCommentHelp',
'',
Justification = 'no need in internal pester helpers.'
)]
param ()
BeforeAll {
$ManifestFile = (Get-Item -Path "./src/*.psd1").FullName
Import-Module $ManifestFile -Force
$PrivateFunctions = (Get-ChildItem -Path "./src/Private/*.ps1" | Where-Object {
$_.BaseName -notmatch '.Tests'
}
).FullName
foreach ( $func in $PrivateFunctions) {
. $func
}
}
Describe "New-CredentialStoreItem" { Describe "New-CredentialStoreItem" {
Context "Private Credential Store tests" { Context "Private Credential Store tests" {
It "Test1: Add entry to existing private store." { It "Add entry to existing private store." {
# Creat a fresh CredentialStore first # Creat a fresh CredentialStore first
New-CredentialStore -Force New-CredentialStore -Force
@ -20,7 +45,7 @@ Describe "New-CredentialStoreItem" {
} }
} }
Context "Test with new shared Credential Store" { Context "Test with new shared Credential Store" {
It "Test2: Create new RemoteHost entry" { It "Create new RemoteHost entry" {
# prepare test environment # prepare test environment
$tmpCS = Join-Path -Path (Get-TempDir) -ChildPath '/CredentialStore.json' $tmpCS = Join-Path -Path (Get-TempDir) -ChildPath '/CredentialStore.json'
New-CredentialStore -Shared -Path $tmpCS -Force New-CredentialStore -Shared -Path $tmpCS -Force
@ -29,9 +54,11 @@ Describe "New-CredentialStoreItem" {
$Password = ConvertTo-SecureString -String "mypasswd" -AsPlainText -Force $Password = ConvertTo-SecureString -String "mypasswd" -AsPlainText -Force
$mycreds = [PSCredential]::new($UserName, $Password) $mycreds = [PSCredential]::new($UserName, $Password)
$RemoteHost = "foobar" $RemoteHost = "foobar"
{ New-CredentialStoreItem -Shared -Path $tmpCS -RemoteHost $RemoteHost -Credential $mycreds } | Should -Not -Throw {
New-CredentialStoreItem -Shared -Path $tmpCS -RemoteHost $RemoteHost -Credential $mycreds
} | Should -Not -Throw
$tmpCS = Get-Content -Path $tmpCS -Raw | ConvertFrom-Json $tmpCS = Get-Content -Path $tmpCS -Raw | ConvertFrom-Json
$res = Get-Member -InputObject $tmpCS -Name $RemoteHost -Membertype Properties $res = Get-Member -InputObject $tmpCS -Name $RemoteHost -MemberType Properties
$res.Name | Should -Be $RemoteHost $res.Name | Should -Be $RemoteHost
} }
It "Adds Item with identifier to shared store" { It "Adds Item with identifier to shared store" {
@ -42,13 +69,19 @@ Describe "New-CredentialStoreItem" {
$Password = ConvertTo-SecureString -String "mypasswd" -AsPlainText -Force $Password = ConvertTo-SecureString -String "mypasswd" -AsPlainText -Force
$mycreds = [PSCredential]::new($UserName, $Password) $mycreds = [PSCredential]::new($UserName, $Password)
$RemoteHost = "foobar2" $RemoteHost = "foobar2"
New-CredentialStoreItem -Shared -Path $tmpCS -RemoteHost $RemoteHost -Credential $mycreds -Identifier 'Foo' $StoreItemParam = @{
Shared = $true
Path = $tmpCS
RemoteHost = $RemoteHost
Credential = $mycreds
identifier = 'Foo'
}
New-CredentialStoreItem @StoreItemParam
$writtenItem = Get-CredentialStoreItem -Shared -Path $tmpCS -RemoteHost $RemoteHost -Identifier 'Foo' $writtenItem = Get-CredentialStoreItem -Shared -Path $tmpCS -RemoteHost $RemoteHost -Identifier 'Foo'
($writtenItem.UserName -eq $UserName) -and ($writtenItem.Password.Length -gt 0) | Should -Be $true ($writtenItem.UserName -eq $UserName) -and ($writtenItem.Password.Length -gt 0) | Should -Be $true
} }
} }
Context "Test optional parameter lookup" { Context "Test optional parameter lookup" {
It "Test missing Credential" { It "Test missing Credential" {
function global:Get-Credential ([string]$Message) { function global:Get-Credential ([string]$Message) {
$UserName = 'testuser' $UserName = 'testuser'
@ -65,16 +98,20 @@ Describe "New-CredentialStoreItem" {
} }
Context "General Exception handling" { Context "General Exception handling" {
Mock Test-CredentialStore { return $false } Mock Test-CredentialStore { return $false } -ModuleName 'PSCredentialStore'
It "Missing CredentialStore should throw" { It "Missing CredentialStore should throw" {
{ New-CredentialStoreItem -Shared -Path 'C:\missingStore.json' -RemoteHost 'notrelevant' } | Should -Throw "Could not add anything" {
New-CredentialStoreItem -Shared -Path '/tmp/missingStore.json' -RemoteHost 'notrelevant'
} | Should -Throw "Could not add anything into the given CredentialStore."
} }
} }
Context "Testing pipeline paramter" { Context "Testing pipeline paramter" {
It "Add the item with credential value from pipe" { It "Add the item with credential value from pipe" {
$UserName = 'pipeUser' $UserName = 'pipeUser'
$Password = ConvertTo-SecureString -String "pipePasswd" -AsPlainText -Force $Password = ConvertTo-SecureString -String "pipePasswd" -AsPlainText -Force
{ [PSCredential]::new($UserName, $Password) | New-CredentialStoreItem -RemoteHost 'PipeHost' } | Should -Not -Throw {
[PSCredential]::new($UserName, $Password) | New-CredentialStoreItem -RemoteHost 'PipeHost'
} | Should -Not -Throw
} }
It "Testing written item" { It "Testing written item" {

11
src/ModuleRoot.psm1 Normal file
View File

@ -0,0 +1,11 @@
#region module-definition
#endregion module-definition
Set-Variable -Name "CSVersion" -Value "2.0.0" -Option Constant -Scope 'Script' -ErrorAction Stop
# Get all child items in the Script path and exclude the Deploy script (if present.)
$Functions = Get-ChildItem -Path $PSScriptRoot\*.ps1 -Recurse | Where-Object { $_.BaseName -notmatch '.Tests' }
foreach ($Item in $Functions) {
. $Item.FullName
}

View File

@ -1,7 +1,7 @@
@{ @{
# Script module or binary module file associated with this manifest. # Script module or binary module file associated with this manifest.
RootModule = 'PSCredentialStore.psm1' RootModule = 'ModuleRoot.psm1'
# Version number of this module. # Version number of this module.
ModuleVersion = '0.0.9999' ModuleVersion = '0.0.9999'

View File

@ -1,16 +0,0 @@
#region module-definition
#endregion module-definition
Set-Variable -Name "CSVersion" -Value "2.0.0" -Option Constant -Scope 'Script' -ErrorAction Stop
#region dot-sourcing
# dot-sourcing all module functions. The export is handled via manifest file.
$Items = (Get-ChildItem -Path (Join-Path -Path $PSScriptRoot -ChildPath '*.ps1') -Recurse ).FullName | Where-Object {
$_ -notmatch "(Classes|Init)"
}
foreach ($Item in $Items) {
# Write-Verbose ("dot sourcing file {0}" -f $Item)
. $Item
}
#endregion dot-sourcing

View File

@ -1,4 +1,5 @@
Describe 'Test module meta' { Describe 'Test module meta' {
Context 'Default tests' -Tag 'Default' {
It 'Test manifest file' { It 'Test manifest file' {
$ManifestFile = (Get-Item -Path "./src/*.psd1").FullName $ManifestFile = (Get-Item -Path "./src/*.psd1").FullName
Test-ModuleManifest -Path $ManifestFile | Should -Be $true Test-ModuleManifest -Path $ManifestFile | Should -Be $true
@ -7,8 +8,5 @@ Describe 'Test module meta' {
$ManifestFile = (Get-Item -Path "./src/*.psd1").FullName $ManifestFile = (Get-Item -Path "./src/*.psd1").FullName
{ Import-Module $ManifestFile } | Should -Not -Throw { Import-Module $ManifestFile } | Should -Not -Throw
} }
# Dummy test to force pester error }
#It 'Force Pester Error' {
# $true | Should -BeFalse
#}
} }

View File

@ -1,3 +1,16 @@
BeforeAll {
$ManifestFile = (Get-Item -Path "./src/*.psd1").FullName
Import-Module $ManifestFile -Force
$PrivateFunctions = (Get-ChildItem -Path "./src/Private/*.ps1" | Where-Object {
$_.BaseName -notmatch '.Tests'
}
).FullName
foreach ( $func in $PrivateFunctions) {
. $func
}
}
Describe "Get-DefaultCredentialStorePath" { Describe "Get-DefaultCredentialStorePath" {
Context "Basic syntax test" { Context "Basic syntax test" {
It "Test1: Should not throw" { It "Test1: Should not throw" {

View File

@ -0,0 +1,20 @@
BeforeAll {
$ManifestFile = (Get-Item -Path "./src/*.psd1").FullName
Import-Module $ManifestFile -Force
$PrivateFunctions = (Get-ChildItem -Path "./src/Private/*.ps1" | Where-Object {
$_.BaseName -notmatch '.Tests'
}
).FullName
foreach ( $func in $PrivateFunctions) {
. $func
}
}
Describe "Get-ModuleBase" {
Context "Basic syntax check" {
It "Test1: Should not throw" {
{ Get-ModuleBase } | Should -Not -Throw
}
}
}

View File

@ -0,0 +1,26 @@
BeforeAll {
$ManifestFile = (Get-Item -Path "./src/*.psd1").FullName
Import-Module $ManifestFile -Force
$PrivateFunctions = (Get-ChildItem -Path "./src/Private/*.ps1" | Where-Object {
$_.BaseName -notmatch '.Tests'
}
).FullName
foreach ( $func in $PrivateFunctions) {
. $func
}
}
Describe "Get-RandomKey" {
Context "Basic input tests" {
It "Test1: Should not throw " {
{ Get-RandomAESKey } | Should -Not -Throw
}
}
Context "Basic syntax check" {
It "Test2: Should return a key with a length of 32 bytes" {
$Key = Get-RandomAESKey
$Key.length | Should -Be 32
}
}
}

View File

@ -1,7 +1,20 @@
BeforeAll {
$ManifestFile = (Get-Item -Path "./src/*.psd1").FullName
Import-Module $ManifestFile -Force
$PrivateFunctions = (Get-ChildItem -Path "./src/Private/*.ps1" | Where-Object {
$_.BaseName -notmatch '.Tests'
}
).FullName
foreach ( $func in $PrivateFunctions) {
. $func
}
}
Describe "Get-TempDir" { Describe "Get-TempDir" {
Context "Basic tests" { Context "Basic tests" {
It "Should not throw" { It "Should not throw" {
{Get-TempDir} | Should -Not -Throw { Get-TempDir } | Should -Not -Throw
} }
It "Should return the correct os tmp path" { It "Should return the correct os tmp path" {
$Path = Get-TempDir $Path = Get-TempDir
@ -17,7 +30,11 @@ Describe "Get-TempDir" {
} }
} }
if ($Env:APPVEYOR) { if ($Env:APPVEYOR) {
if (($isWindows) -or ($PSVersionTable.PSVersion.Major -lt 6) -or ($PSVersionTable.PSEdition -eq 'Desktop')) { if (
($isWindows) -or
($PSVersionTable.PSVersion.Major -lt 6) -or
($PSVersionTable.PSEdition -eq 'Desktop')
) {
$RefPath = (Resolve-Path -Path $env:TEMP).Path $RefPath = (Resolve-Path -Path $env:TEMP).Path
$Path | Should -Be $RefPath $Path | Should -Be $RefPath
} }

View File

@ -0,0 +1,60 @@
BeforeAll {
$ManifestFile = (Get-Item -Path "./src/*.psd1").FullName
Import-Module $ManifestFile -Force
$PrivateFunctions = (Get-ChildItem -Path "./src/Private/*.ps1" | Where-Object {
$_.BaseName -notmatch '.Tests'
}
).FullName
foreach ( $func in $PrivateFunctions) {
. $func
}
}
Describe "Resolve-Dependency" {
Context "Basic syntax check" {
BeforeAll {
Mock Get-ModuleBase {
return (Join-Path -Path $PWD -ChildPath '/resources')
}
Mock Test-Module {
return $true
}
}
It "Test1: Should not throw" {
{ Resolve-Dependency -Name 'foobar2000' } | Should -Not -Throw
}
It "Test2: Output type should be bool" {
Resolve-Dependency -Name 'foobar2000' | Should -BeOfType bool
}
}
Context "Enforce Error" {
# Return incorrect module base to enforce there is no config file.
Mock Get-ModuleBase {
if ($IsWindows) { return "C:\" }
elseif ($isLinux) { return "/" }
}
It "Missing dependency file should not cause an error" {
{ Resolve-Dependency -Name 'awesome' } | Should -Not -Throw
}
It "Missing dependency file should return true" {
Resolve-Dependency -Name 'awesome' | Should -Be $true
}
}
Context "Testing input variations" {
It "Should return true if all given dependencies exist" {
Mock Get-ModuleBase {
return (Join-Path -Path $PWD -ChildPath '/resources')
}
Resolve-Dependency -Name 'Existing' | Should -Be $true
}
It "Mixed results should return false" {
Mock Get-ModuleBase {
return (Join-Path -Path $PWD -ChildPath '/resources')
}
Resolve-Dependency -Name 'PSGetMixed' | Should -Be $false
}
}
}

View File

@ -0,0 +1,25 @@
BeforeAll {
$ManifestFile = (Get-Item -Path "./src/*.psd1").FullName
Import-Module $ManifestFile -Force
$PrivateFunctions = (Get-ChildItem -Path "./src/Private/*.ps1" | Where-Object {
$_.BaseName -notmatch '.Tests'
}
).FullName
foreach ( $func in $PrivateFunctions) {
. $func
}
}
Describe "Test-CSPfxCertificate" {
Context "Basic Tests" {
It "Should not Throw" {
{
Test-CSPfxCertificate -Thumbprint '12345' -StoreName My -StoreLocation CurrentUser
} | Should -Not -Throw
}
It "Should return false" {
Test-CSPfxCertificate -Thumbprint '12345' -StoreName My -StoreLocation CurrentUser | Should -Be $false
}
}
}

View File

@ -1,3 +1,16 @@
BeforeAll {
$ManifestFile = (Get-Item -Path "./src/*.psd1").FullName
Import-Module $ManifestFile -Force
$PrivateFunctions = (Get-ChildItem -Path "./src/Private/*.ps1" | Where-Object {
$_.BaseName -notmatch '.Tests'
}
).FullName
foreach ( $func in $PrivateFunctions) {
. $func
}
}
Describe "Test-ModuleName" { Describe "Test-ModuleName" {
Context "Basic input tests" { Context "Basic input tests" {
It "Testing standard module should not throw" { It "Testing standard module should not throw" {
@ -20,7 +33,7 @@ Describe "Test-ModuleName" {
Test-Module -Name 'foobar2000' | Should -Be $false Test-Module -Name 'foobar2000' | Should -Be $false
} }
It "StopifFails switch should thrown an error" { It "StopifFails switch should thrown an error" {
{Test-Module -Name 'foobar2000' -StopIfFails }| Should -Throw { Test-Module -Name 'foobar2000' -StopIfFails } | Should -Throw
} }
} }
} }

View File

@ -0,0 +1,47 @@
BeforeAll {
$ManifestFile = (Get-Item -Path "./src/*.psd1").FullName
Import-Module $ManifestFile -Force
$PrivateFunctions = (Get-ChildItem -Path "./src/Private/*.ps1" | Where-Object {
$_.BaseName -notmatch '.Tests'
}
).FullName
foreach ( $func in $PrivateFunctions) {
. $func
}
}
Describe "Get-CredentialStore" {
Context "Basic logic tests" {
It "Read CS without params" {
$TestCredentialStore = './resources/cs/CredentialStore.json'
$TestPfxCert = './resources/cs/PSCredentialStore.pfx'
if (! (Test-Path -Path (Get-DefaultCredentialStorePath)) ) {
{ New-CredentialStore -Force } | Should -Not -Throw
}
{ Get-CredentialStore } | Should -Not -Throw
}
It "Read Credential Store with testing data" {
$TestCredentialStore = './resources/cs/CredentialStore.json'
$TestPfxCert = './resources/cs/PSCredentialStore.pfx'
{
Use-CSCertificate -Shared -CredentialStore $TestCredentialStore -Path $TestPfxCert
} | Should -Not -Throw
{ Get-CredentialStore -Shared -Path $TestCredentialStore } | Should -Not -Throw
}
It "Test3: Not existing path should return false" {
{
Get-CredentialStore -Shared -Path './CredentialStore.json'
} | Should -Throw "Could not find the CredentialStore."
}
}
Context "Testing invalid json data" {
It "Should throw with invalid CredentialStore" {
$BrokenCS = './resources/cs/Broken_CS.json'
Write-Verbose -Message ('BrokenCS Path: {0}' -f $BrokenCS) -Verbose
{
Get-CredentialStore -Path -Shared $BrokenCS
} | Should -Throw
}
}
}

View File

@ -0,0 +1,141 @@
BeforeAll {
$ManifestFile = (Get-Item -Path "./src/*.psd1").FullName
Import-Module $ManifestFile -Force
$PrivateFunctions = (Get-ChildItem -Path "./src/Private/*.ps1" | Where-Object {
$_.BaseName -notmatch '.Tests'
}
).FullName
foreach ( $func in $PrivateFunctions) {
. $func
}
# Backup existing credential stores
$VerbosePreference = "Continue"
Write-Verbose "Backup private Credential Store..."
$CSPath = Get-DefaultCredentialStorePath
$BackupFile = "{0}.back" -f $CSPath
if (Test-Path -Path $CSPath) {
Move-Item -Path $CSPath -Destination $BackupFile
}
Write-Verbose "Backup shared CredentialStore..."
$CSShared = Get-DefaultCredentialStorePath -Shared
$BackupSharedFile = "{0}.back" -f $CSShared
if (Test-Path -Path $CSShared) {
Move-Item -Path $CSShared -Destination $BackupSharedFile
}
Write-Verbose "Remove old CredentialStore in Temp dir"
$CSTemp = Join-Path -Path (Get-TempDir) -ChildPath '/CredentialStore.json'
if (Test-Path -Path $CSTemp) {
Remove-Item -Path $CSTemp
}
$VerbosePreference = "SilentlyContinue"
}
Describe "New-CredentialStore" {
Context "Private CS tests" {
It "Create new private CredentialStore" {
$pCS = Get-DefaultCredentialStorePath
{ New-CredentialStore -Confirm:$false -Force } | Should -Not -Throw
$result = Test-Path -Path $pCS
$CS = Get-Content -Path $pCS -Raw | ConvertFrom-Json
($result -eq $true) -and ($CS.Type -eq "Private") | Should -Be $true
}
It "Try to override private Store" {
{ New-CredentialStore -Confirm:$false } | Should -Throw
}
It "Reset existing Credential Store" {
$pCS = Get-DefaultCredentialStorePath
$now = Get-Date
$CS = Get-Content -Path $pCS -Raw | ConvertFrom-Json
$CSCreation = [DateTime]$CS.Created
New-CredentialStore -Confirm:$false -Force
$now -gt $csCreation | Should -Be $true
}
}
Context "Shared CS tests" {
It "Create a new Shared Credential Store" {
$sCS = Get-DefaultCredentialStorePath -Shared
{ New-CredentialStore -Confirm:$false -Shared } | Should -Not -Throw
Test-Path -Path $sCS | Should -Be $true
}
It "Try to override existing shared CS" {
{ New-CredentialStore -Shared -Confirm:$false } | Should -Throw
}
It "Reset shared CredentialStore" {
$sCS = Get-DefaultCredentialStorePath -Shared
$now = Get-Date
$CS = Get-Content -Path $sCS -Raw | ConvertFrom-Json
$CSCreation = [DateTime]$CS.Created
New-CredentialStore -Force -Shared -Confirm:$false
$now -gt $csCreation | Should -Be $true
}
}
Context "Custom Shared CS tests" {
It "Create new custom shared" {
$cCS = Join-Path -Path (Get-TempDir) -ChildPath "CredentialStore.json"
{ New-CredentialStore -Path $cCS -Shared -Confirm:$false -SkipPFXCertCreation } | Should -Not -Throw
}
It "Try to override exiting one" {
$cCS = Join-Path -Path (Get-TempDir) -ChildPath "CredentialStore.json"
{ New-CredentialStore -Path $cCS -Shared -Confirm:$false } | Should -Throw
}
It "Reset existing custom CredentialStore" {
$cCS = Join-Path -Path (Get-TempDir) -ChildPath "CredentialStore.json"
{ New-CredentialStore -Path $cCS -Shared -Force -Confirm:$false } | Should -Not -Throw
}
}
Context "Test exception handling" {
Mock Out-File { throw "foobar exception" }
It "JSON Conversion should fail and throw" {
{
New-CredentialStore -Path (
Join-Path -Path (Get-TempDir) -ChildPath '/dummy.json'
) -Shared -Confirm:$false
} | Should -Throw
}
}
Context "Tests for Windows certificate store" {
It "Create new private store and skip certificate linking" {
{ New-CredentialStore -UseCertStore -Force } | Should -Not -Throw
$CS = Get-CredentialStore
$CS.PfxCertificate | Should -Be $null
$CS.Thumbprint | Should -Not -Be $null
$res = Test-CSCertificate -Type Private
#Write-Verbose -Message ('res: {0}' -f $res) -Verbose
$res | Should -Be $true
}
It "Create new shared store and skipt certificate linking" {
{ New-CredentialStore -Shared -UseCertStore -Force } | Should -Not -Throw
$CS = Get-CredentialStore -Shared
$CS.PfxCertificate | Should -Be $null
$CS.Thumbprint | Should -Not -Be $null
$res = Test-CSCertificate -Type Shared
#Write-Verbose -Message ('res: {0}' -f $res) -Verbose
$res | Should -Be $true
}
}
}
AfterAll {
# Cleanup test stores and restore existing ones.
$VerbosePreference = "Continue"
Write-Verbose "Restoring private CredentialStore"
If (Test-Path -Path $BackupFile) {
If (Test-Path -Path $CSPath) {
Remove-Item -Path $CSPath
Move-Item -Path $BackupFile -Destination $CSPath
}
}
Write-Verbose "Restoring shared CredentialStore"
If (Test-Path -Path $BackupSharedFile) {
If (Test-Path -Path $CSShared) {
Remove-Item -Path $CSShared
Move-Item -Path $BackupSharedFile -Destination $CSShared
}
}
$VerbosePreference = "SilentlyContinue"
}

View File

@ -1,24 +1,36 @@
$RepoRoot = (Get-Item -Path (Get-GitDirectory) -Force).Parent | Select-Object -ExpandProperty 'FullName' BeforeAll {
$ManifestFile = (Get-Item -Path "./src/*.psd1").FullName
Import-Module $ManifestFile -Force
$PrivateFunctions = (Get-ChildItem -Path "./src/Private/*.ps1" | Where-Object {
$_.BaseName -notmatch '.Tests'
}
).FullName
foreach ( $func in $PrivateFunctions) {
. $func
}
}
Describe "Test-CredentialStore" { Describe "Test-CredentialStore" {
Context "Basic logic tests" { Context "Basic logic tests" {
$TestCredentialStore = Join-Path -Path $RepoRoot -ChildPath '/resources/cs/CredentialStore.json' It "Should Not Throw" {
It "Test1: Should Not Throw" { $TestCredentialStore = './resources/cs/CredentialStore.json'
{ Test-CredentialStore -Shared -Path $TestCredentialStore } | Should -Not -Throw { Test-CredentialStore -Shared -Path $TestCredentialStore } | Should -Not -Throw
} }
It "Test2: Read valid CredentialStore" { It "Read valid CredentialStore" {
$TestCredentialStore = './resources/cs/CredentialStore.json'
$res = Test-CredentialStore -Shared -Path $TestCredentialStore $res = Test-CredentialStore -Shared -Path $TestCredentialStore
$res | Should -Be $true $res | Should -Be $true
} }
It "Test3: Read a broken CredentialStore" { It "Read a broken CredentialStore" -Skip {
$BrokenCS = Join-Path -Path $RepoRoot -ChildPath '{0}/resources/cs/Broken_CS.json' $BrokenCS = './resources/cs/Broken_CS.json'
$oWarningPreference = $WarningPreference $oWarningPreference = $WarningPreference
$WarningPreference = 'SilentlyContinue' $WarningPreference = 'SilentlyContinue'
$res = Test-CredentialStore -Shared -Path $BrokenCS $res = Test-CredentialStore -Shared -Path $BrokenCS
$res | Should -Be $false $res | Should -Be $false
$WarningPreference = $oWarningPreference $WarningPreference = $oWarningPreference
} }
It "Test4: Not existing path should return false" { It "Not existing path should return false" {
if ($isWindows -or ($PSVersionTable.PSVersion.Major -eq 5)) { if ($isWindows -or ($PSVersionTable.PSVersion.Major -eq 5)) {
Test-CredentialStore -Shared -Path 'C:\foobar\CredentialStore.json' | Should -Be $false Test-CredentialStore -Shared -Path 'C:\foobar\CredentialStore.json' | Should -Be $false
} }
@ -26,7 +38,7 @@ Describe "Test-CredentialStore" {
Test-CredentialStore -Shared -Path '/var/opt/foo.json' | Should -Be $false Test-CredentialStore -Shared -Path '/var/opt/foo.json' | Should -Be $false
} }
} }
It "Test5: testing private CredentialStore path" { It "testing private CredentialStore path" {
if (Test-Path -Path (Get-DefaultCredentialStorePath)) { if (Test-Path -Path (Get-DefaultCredentialStorePath)) {
Remove-Item -Path (Get-DefaultCredentialStorePath) Remove-Item -Path (Get-DefaultCredentialStorePath)
} }

View File

View File

@ -1,17 +0,0 @@
$RepoRoot = (Get-Item -Path (Get-GitDirectory) -Force).Parent | Select-Object -ExpandProperty 'FullName'
Write-Verbose -Message ('RepoRoot: {0}' -f $RepoRoot) -Verbose
$ManifestFilePath = Join-Path -Path $RepoRoot -ChildPath '/src/PSCredentialStore.psd1'
Write-Verbose -Message ("ManifestFilePath: {0}" -f $ManifestFilePath) -Verbose
Describe "Pre-Flight module tests" {
Context "Manifest file related" {
It "Test the parsed file itself" {
{ Test-ModuleManifest -Path $ManifestFilePath -Verbose } | Should -Not -Throw
}
}
Context "Module consistency tests" {
It "Importing should work" {
{ Import-Module -Name $ManifestFilePath -Global -Force -Verbose } | Should -Not -Throw
}
}
}

View File

@ -1,7 +0,0 @@
Describe "New-CSCertAttribute" {
Context "Basis Tests" {
It "Test1: Should not throw " {
{ New-CSCertAttribute -Country 'DE' -State 'BW' -City 'KA' -Organization 'IT' -OrganizationalUnitName'' -CommonName 'Mycert' } | Should -Not -Throw
}
}
}

View File

@ -1,15 +0,0 @@
Describe "New-CSCertificate" {
Context "Basic Tests" {
It "Test1: Should not throw" {
$attribs = New-CSCertAttribute -Country 'DE' -State 'BW' -City 'KA' -Organization 'IT' -OrganizationalUnitName'' -CommonName 'Mycert'
$CertAttribs = @{
CRTAttribute = $attribs
KeyName = Join-Path -Path (Get-TempDir) -ChildPath '/foo.key'
CertName = Join-Path -Path (Get-TempDir) -ChildPath '/cert.pfx'
}
{ New-CSCertificate @CertAttribs } | Should -Not -Throw
}
}
}

View File

@ -1,10 +0,0 @@
Describe "Test-CSPfxCertificate" {
Context "Basic Tests" {
It "Should not Throw" {
{ Test-CSPfxCertificate -Thumbprint '12345' -StoreName My -StoreLocation CurrentUser } | Should -Not -Throw
}
It "Should return false" {
Test-CSPfxCertificate -Thumbprint '12345' -StoreName My -StoreLocation CurrentUser | Should -Be $false
}
}
}

View File

@ -1,7 +0,0 @@
Describe "Get-ModuleBase" {
Context "Basic syntax check" {
It "Test1: Should not throw" {
{ Get-ModuleBase } | Should -Not -Throw
}
}
}

View File

@ -1,13 +0,0 @@
Describe "Get-RandomKey" {
Context "Basic input tests" {
It "Test1: Should not throw " {
{Get-RandomAESKey} | Should -Not -Throw
}
}
Context "Basic syntax check" {
It "Test2: Should return a key with a length of 32 bytes" {
$Key = Get-RandomAESKey
$Key.length | Should -Be 32
}
}
}

View File

@ -1,35 +0,0 @@
Describe "Resolve-Dependency" {
Context "Basic syntax check" {
Mock Get-ModuleBase {return (Join-Path -Path $PWD -ChildPath '/resources')}
Mock Test-Module {return $true}
It "Test1: Should not throw" {
{ Resolve-Dependency -Name 'foobar2000' } | Should -Not -Throw
}
It "Test2: Output type should be bool" {
Resolve-Dependency -Name 'foobar2000' | Should -BeOfType bool
}
}
Context "Enforce Error" {
# Return incorrect module base to enforce there is no config file.
Mock Get-ModuleBase {
if ($IsWindows) {return "C:\"}
elseif ($isLinux) {return "/"}
}
It "Missing dependency file should not cause an error" {
{ Resolve-Dependency -Name 'awesome'} | Should -Not -Throw
}
It "Missing dependency file should return true" {
Resolve-Dependency -Name 'awesome' | Should -Be $true
}
}
Context "Testing input variations" {
Mock Get-ModuleBase {return (Join-Path -Path $PWD -ChildPath '/resources')}
It "Should return true if all given dependencies exist" {
Resolve-Dependency -Name 'Existing' | Should -Be $true
}
It "Mixed results should return false" {
Resolve-Dependency -Name 'PSGetMixed' | Should -Be $false
}
}
}

View File

@ -1,117 +0,0 @@
# Backup existing credential stores
$VerbosePreference = "Continue"
Write-Verbose "Backup private Credential Store..."
$CSPath = Get-DefaultCredentialStorePath
$BackupFile = "{0}.back" -f $CSPath
If (Test-Path -Path $CSPath) {
Move-Item -Path $CSPath -Destination $BackupFile
}
Write-Verbose "Backup shared CredentialStore..."
$CSShared = Get-DefaultCredentialStorePath -Shared
$BackupSharedFile = "{0}.back" -f $CSShared
If (Test-Path -Path $CSShared) {
Move-Item -Path $CSShared -Destination $BackupSharedFile
}
Write-Verbose "Remove old CredentialStore in Temp dir"
$CSTemp = Join-Path -Path (Get-TempDir) -ChildPath '/CredentialStore.json'
If (Test-Path -Path $CSTemp) {
Remove-Item -Path $CSTemp
}
$VerbosePreference = "SilentlyContinue"
Describe "New-CredentialStore" {
Context "Private CS tests" {
$pCS = Get-DefaultCredentialStorePath
It "Test1: Create new private CredentialStore" {
{ New-CredentialStore -Confirm:$false } | Should -Not -Throw
$result = Test-Path -Path $pCS
$CS = Get-Content -Path $pCS -Raw | ConvertFrom-Json
($result -eq $true) -and ($CS.Type -eq "Private") | Should -Be $true
}
It "Test2: Try to override private Store" {
{ New-CredentialStore -Confirm:$false } | Should -Throw
}
It "Test3: Reset existing Credential Store" {
$now = Get-Date
$CS = Get-Content -Path $pCS -Raw | ConvertFrom-Json
$CSCreation = [DateTime]$CS.Created
New-CredentialStore -Confirm:$false -Force
$now -gt $csCreation | Should -Be $true
}
}
Context "Shared CS tests" {
$sCS = Get-DefaultCredentialStorePath -Shared
It "Test1: Create a new Shared Credential Store" {
{ New-CredentialStore -Confirm:$false -Shared } | Should -Not -Throw
Test-Path -Path $sCS | Should -Be $true
}
It "Test2: Try to override existing shared CS" {
{ New-CredentialStore -Shared -Confirm:$false } | Should -Throw
}
It "Test3: Reset shared CredentialStore" {
$now = Get-Date
$CS = Get-Content -Path $sCS -Raw | ConvertFrom-Json
$CSCreation = [DateTime]$CS.Created
New-CredentialStore -Force -Shared -Confirm:$false
$now -gt $csCreation | Should -Be $true
}
}
Context "Custom Shared CS tests" {
$cCS = Join-Path -Path (Get-TempDir) -ChildPath "CredentialStore.json"
It "Test1: Create new custom shared" {
{ New-CredentialStore -Path $cCS -Shared -Confirm:$false } | Should -Not -Throw
}
It "Test2: Try to override exiting one" {
{ New-CredentialStore -Path $cCS -Shared -Confirm:$false } | Should -Throw
}
It "Test3: Reset existing custom CredentialStore" {
{ New-CredentialStore -Path $cCS -Shared -Force -Confirm:$false } | Should -Not -Throw
}
}
Context "Test exception handling" {
Mock Out-File { throw "foobar exception" }
It "JSON Conversion should fail and throw" {
{ New-CredentialStore -Path (Join-Path -Path (Get-TempDir) -ChildPath '/dummy.json') -Shared -Confirm:$false } | Should -Throw
}
}
Context "Tests for Windows certificate store" {
It "Create new private store and skip certificate linking" {
{ New-CredentialStore -UseCertStore -Force } | Should -Not -Throw
$CS = Get-CredentialStore
$CS.PfxCertificate | Should -Be $null
$CS.Thumbprint | Should -Not -Be $null
$res = Test-CSCertificate -Type Private
#Write-Verbose -Message ('res: {0}' -f $res) -Verbose
$res | Should -Be $true
}
It "Create new shared store and skipt certificate linking" {
{ New-CredentialStore -Shared -UseCertStore -Force } | Should -Not -Throw
$CS = Get-CredentialStore -Shared
$CS.PfxCertificate | Should -Be $null
$CS.Thumbprint | Should -Not -Be $null
$res = Test-CSCertificate -Type Shared
#Write-Verbose -Message ('res: {0}' -f $res) -Verbose
$res | Should -Be $true
}
}
}
# Cleanup test stores and restore existing ones.
$VerbosePreference = "Continue"
Write-Verbose "Restoring private CredentialStore"
If (Test-Path -Path $BackupFile) {
If (Test-Path -Path $CSPath) {
Remove-Item -Path $CSPath
Move-Item -Path $BackupFile -Destination $CSPath
}
}
Write-Verbose "Restoring shared CredentialStore"
If (Test-Path -Path $BackupSharedFile) {
If (Test-Path -Path $CSShared) {
Remove-Item -Path $CSShared
Move-Item -Path $BackupSharedFile -Destination $CSShared
}
}
$VerbosePreference = "SilentlyContinue"

View File

@ -1,32 +0,0 @@
$RepoRoot = (Get-Item -Path (Get-GitDirectory) -Force).Parent | Select-Object -ExpandProperty 'FullName'
Describe "Get-CredentialStore" {
Context "Basic logic tests" {
$TestCredentialStore = Join-Path -Path $RepoRoot -ChildPath 'resources/cs/CredentialStore.json'
$TestPfxCert = Join-Path -Path $RepoRoot -ChildPath 'resources/cs/PSCredentialStore.pfx'
'TestCredentialStore: {0}' -f $TestCredentialStore
It "Test1: Read CS without params" {
if (! (Test-Path -Path (Get-DefaultCredentialStorePath)) ) {
{ New-CredentialStore -Force } | Should -Not -Throw
}
{ Get-CredentialStore } | Should -Not -Throw
}
It "Test2: Read Credential Store with testing data" {
{ Use-CSCertificate -Shared -CredentialStore $TestCredentialStore -Path $TestPfxCert } | Should -Not -Throw
{ Get-CredentialStore -Shared -Path $TestCredentialStore } | Should -Not -Throw
}
It "Test3: Not existing path should return false" {
{ Get-CredentialStore -Shared -Path './CredentialStore.json' } | Should -Throw "Could not find the CredentialStore."
}
}
Context "Testing invalid json data" {
#Mock Test-CredentialStore {return $true}
#Mock Get-Content {return '"foo":"bar",'}
$BrokenCS = Join-Path -Path $RepoRoot -ChildPath 'resources/cs/Broken_CS.json'
Write-Verbose -Message ('BrokenCS Path: {0}' -f $BrokenCS) -Verbose
It "Should throw with invalid CredentialStore" {
{ Get-CredentialStore -Path -Shared $BrokenCS } | Should -Throw
}
}
}

View File

@ -80,6 +80,35 @@ function Invoke-InstallDependencies {
} }
} }
function Start-PSScriptAnalyzer {
[CmdletBinding()]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSUseShouldProcessForStateChangingFunctions',
'',
Justification = 'justification'
)]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSProvideCommentHelp',
'',
Justification = 'internal function'
)]
param ()
process {
$AnalyzerSettings = @{
Path = './src/'
Recurse = $true
Settings = './tools/PSScriptAnalyzerSettings.psd1'
ReportSummary = $true
ErrorAction = 'Stop'
}
$AnalyzerResults = Invoke-ScriptAnalyzer @AnalyzerSettings
if ( $AnalyzerResults ) {
Write-Output -InputObject $AnalyzerResults
}
}
}
function Invoke-Linter { function Invoke-Linter {
[CmdletBinding()] [CmdletBinding()]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute( [Diagnostics.CodeAnalysis.SuppressMessageAttribute(
@ -90,16 +119,20 @@ function Invoke-Linter {
param () param ()
process { process {
Import-Module -Name PSScriptAnalyzer
$AnalyzerSettings = @{
Path = './src/'
Recurse = $true
Settings = './tools/PSScriptAnalyzerSettings.psd1'
ReportSummary = $true
ErrorAction = 'Stop'
}
try { try {
$AnalyzerResults = Invoke-ScriptAnalyzer @AnalyzerSettings $AnalyzerResults = Start-PSScriptAnalyzer
}
catch {
Write-Debug -Message $_.Exception.Message -Debug
if ($_.Exception.Message -match 'Object reference not set') {
Write-Debug -Message 'ReRun PSScriptAnalyzer' -Debug
$AnalyzerResults = Start-PSScriptAnalyzer
}
else {
Write-Error -Message 'PSScriptAnalyzer failer'
}
}
finally {
if ( $AnalyzerResults ) { if ( $AnalyzerResults ) {
$AnalyzerResults | Sort-Object -Property @( $AnalyzerResults | Sort-Object -Property @(
"ScriptName", "ScriptName",
@ -111,12 +144,10 @@ function Invoke-Linter {
"RuleName", "RuleName",
"Message" "Message"
) -AutoSize | Out-String | Write-Verbose -Verbose ) -AutoSize | Out-String | Write-Verbose -Verbose
Update-BuildStateFile
throw 'PS Script Analyzer failed!'
} }
} }
catch {
Write-Debug -Message $_.Exception.Message -Debug
Write-Error -Message 'PSScriptAnalyzer failer'
}
} }
} }
@ -171,8 +202,49 @@ function Invoke-UnitTest {
$PesterConf.Filter.ExcludeTag = $ExcludeTag $PesterConf.Filter.ExcludeTag = $ExcludeTag
} }
$TestResults = Invoke-Pester -Configuration $PesterConf -ErrorAction 'Stop' $TestResults = Invoke-Pester -Configuration $PesterConf -ErrorAction 'Stop'
if ($TestResults.FailedCount -gt 0) {
Update-BuildStateFile
throw ('{0} tests failed!' -f $TestResults.FailedCount)
}
if ($PassThru.IsPresent) { if ($PassThru.IsPresent) {
Write-Output -InputObject $TestResults Write-Output -InputObject $TestResults
} }
} }
} }
function Update-BuildStateFile {
[CmdletBinding()]
param (
[Parameter(Mandatory = $false)]
[ValidateNotNullOrEmpty()]
[string]$StepName = $Env:DRONE_FAILED_STEPS
)
process {
$StateFilePath = Join-Path -Path $PWD -ChildPath './STATE.xml'
if (Test-Path -Path $StateFilePath) {
$StateContent = Import-Clixml -Path $StateFilePath
$StateContent.Steps += $StepName
}
else {
$StateContent = [PSCustomObject]@{
Steps = @($StepName)
}
}
Export-Clixml -Path $StateFilePath -InputObject $StateContent -Force -Encoding utf8NoBOM
}
}
function Invoke-BuildState {
[CmdletBinding()]
param ()
process {
$StateFilePath = Join-Path -Path $PWD -ChildPath './STATE.xml'
if ( Test-Path -Path $StateFilePath ) {
throw 'One one more pipeline steps failed. Marking the pipeline as failed!'
}
}
}