mirror of
https://github.com/PowerShell/PSDscResources
synced 2026-06-21 13:45:29 +00:00
adding msiPackage
This commit is contained in:
committed by
Katie Keim
parent
19ffca486a
commit
8303c0e7fc
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
||||
[ClassVersion("1.0.0"),FriendlyName("MsiPackage")]
|
||||
class MSFT_MsiPackage : OMI_BaseResource
|
||||
{
|
||||
[Key, Description("The identifying number used to find the package, usually a GUID.")] String ProductId;
|
||||
[Required, Description("The path to the MSI file that should be installed or uninstalled.")] String Path;
|
||||
[Write, Description("Specifies whether or not the MSI file should be installed or uninstalled."), ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] String Ensure;
|
||||
[Write, Description("The arguments to be passed to the MSI package during installation or uninstallation.")] String Arguments;
|
||||
[Write, Description("The credential of a user account to be used to mount a UNC path if needed."), EmbeddedInstance("MSFT_Credential")] String Credential;
|
||||
[Write, Description("The path to the log file to log the output from the MSI execution.")] String LogPath;
|
||||
[Write, Description("The expected hash value of the MSI file at the given path.")] String FileHash;
|
||||
[Write, Description("The algorithm used to generate the given hash value."), ValueMap{"SHA1", "SHA256", "SHA384", "SHA512", "MD5", "RIPEMD160"}, Values{"SHA1", "SHA256", "SHA384", "SHA512", "MD5", "RIPEMD160"}] String HashAlgorithm;
|
||||
[Write, Description("The subject that should match the signer certificate of the digital signature of the MSI file.")] String SignerSubject;
|
||||
[Write, Description("The certificate thumbprint that should match the signer certificate of the digital signature of the MSI file.")] String SignerThumbprint;
|
||||
[Write, Description("PowerShell code that should be used to validate SSL certificates for paths using HTTPS.")] String ServerCertificateValidationCallback;
|
||||
[Write, Description("The credential of a user account under which to run the installation or uninstallation of the MSI package."), EmbeddedInstance("MSFT_Credential")] String RunAsCredential;
|
||||
[Read, Description("The display name of the MSI package.")] String Name;
|
||||
[Read, Description("The path to the MSI package.")] String InstallSource;
|
||||
[Read, Description("The date that the MSI package was installed on or serviced on, whichever is later.")] String InstalledOn;
|
||||
[Read, Description("The size of the MSI package in MB.")] UInt32 Size;
|
||||
[Read, Description("The version number of the MSI package.")] String Version;
|
||||
[Read, Description("The description of the MSI package.")] String PackageDescription;
|
||||
[Read, Description("The publisher of the MSI package.")] String Publisher;
|
||||
};
|
||||
Binary file not shown.
@@ -0,0 +1,44 @@
|
||||
# Localized resources for MSFT_MsiPackage
|
||||
|
||||
ConvertFrom-StringData @'
|
||||
CheckingFileHash = Checking file '{0}' for expected {2} hash value of {1}
|
||||
CheckingFileSignature = Checking file '{0}' for valid digital signature
|
||||
CopyingTheSchemeStreamBytesToTheDiskCache = Copying the stream bytes to the disk cache
|
||||
CouldNotGetResponseFromWebRequest = An error occurred while trying to get the {0} response for file {1}
|
||||
CouldNotOpenDestFile = Could not open the file {0} for writing
|
||||
CouldNotOpenLog = The specified LogPath ({0}) could not be opened
|
||||
CouldNotStartProcess = The process {0} could not be started
|
||||
CreatingCacheLocation = Creating cache location
|
||||
CreatingTheDestinationCacheFile = Creating the destination cache file
|
||||
CreatingTheSchemeStream = Creating the {0} stream
|
||||
ErrorCopyingDataToFile = Encountered an error while copying the response to the output stream
|
||||
FileHasValidSignature = File '{0}' contains a valid digital signature. Signer Thumbprint: {1}, Subject: {2}
|
||||
GetTargetResourceFound = Successfully retrieved package {0}
|
||||
GetTargetResourceNotFound = Unable to find package: {0}
|
||||
GettingTheSchemeResponseStream = Getting the {0} response stream
|
||||
InvalidBinaryType = The specified Path ({0}) does not appear to specify an MSI file and as such is not supported
|
||||
InvalidFileHash = File '{0}' does not match expected {2} hash value of {1}
|
||||
InvalidFileSignature = File '{0}' does not have a valid Authenticode signature. Status: {1}
|
||||
InvalidId = The specified IdentifyingNumber ({0}) does not match the IdentifyingNumber ({1}) in the MSI file
|
||||
InvalidIdentifyingNumber = The specified IdentifyingNumber ({0}) is not a valid GUID
|
||||
InvalidPath = The specified Path ({0}) is not in a valid format. Valid formats are local paths, UNC, HTTP, and HTTPS
|
||||
MachineRequiresReboot = The machine requires a reboot
|
||||
PackageAppearsInstalled = The package {0} is installed
|
||||
PackageConfigurationStarting = Package configuration starting
|
||||
PackageDoesNotAppearInstalled = The package {0} is not installed
|
||||
PathDoesNotExist = The given Path ({0}) could not be found
|
||||
PackageInstalled = Package has been installed
|
||||
PackageUninstalled = Package has been uninstalled
|
||||
ParsedProductIdAsIdentifyingNumber = Parsed {0} as {1}
|
||||
ParsingProductIdAsAnIdentifyingNumber = Parsing {0} as an identifyingNumber
|
||||
PostValidationError = Package from {0} was installed, but the specified ProductId does not match package details
|
||||
RedirectingPackagePathToCacheFileLocation = Redirecting package path to cache file location
|
||||
SettingAuthenticationLevel = Setting authentication level to None
|
||||
SettingCertificateValidationCallback = Assigning user-specified certificate verification callback
|
||||
SettingDefaultCredential = Setting default credential
|
||||
StartingWithStartInfoFileNameStartInfoArguments = Starting {0} with {1}
|
||||
ThePathExtensionWasPathExt = The path extension was {0}
|
||||
TheUriSchemeWasUriScheme = The uri scheme was {0}
|
||||
WrongSignerSubject = File '{0}' was not signed by expected signer subject '{1}'
|
||||
WrongSignerThumbprint = File '{0}' was not signed by expected signer certificate thumbprint '{1}'
|
||||
'@
|
||||
@@ -0,0 +1,28 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Installs the MSI file with the product ID: '{DEADBEEF-80C6-41E6-A1B9-8BDB8A05027F}'
|
||||
at the path: 'file://Examples/example.msi'.
|
||||
|
||||
Note that the MSI file with the given product ID must already exist at the specified path.
|
||||
The product ID and path value in this file are provided for example purposes only and will
|
||||
need to be replaced with valid values.
|
||||
|
||||
You can run the following command to get a list of all available MSIs on
|
||||
your system with the correct Path (LocalPackage) and product ID (IdentifyingNumber):
|
||||
|
||||
Get-WmiObject Win32_Product | Format-Table IdentifyingNumber, Name, LocalPackage
|
||||
#>
|
||||
Configuration Sample_MsiPackage_InstallPackageFromFile
|
||||
{
|
||||
Import-DscResource -ModuleName 'PSDscResources'
|
||||
|
||||
Node localhost
|
||||
{
|
||||
MsiPackage MsiPackage1
|
||||
{
|
||||
ProductId = '{DEADBEEF-80C6-41E6-A1B9-8BDB8A05027F}'
|
||||
Path = 'file://Examples/example.msi'
|
||||
Ensure = 'Present'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Installs the MSI file with the product ID: '{DEADBEEF-80C6-41E6-A1B9-8BDB8A05027F}'
|
||||
at the path: 'http://Examples/example.msi'.
|
||||
|
||||
Note that the MSI file with the given product ID must already exist on the server.
|
||||
The product ID and path value in this file are provided for example purposes only and will
|
||||
need to be replaced with valid values.
|
||||
#>
|
||||
Configuration Sample_MsiPackage_InstallPackageFromHttp
|
||||
{
|
||||
Import-DscResource -ModuleName 'PSDscResources'
|
||||
|
||||
Node localhost
|
||||
{
|
||||
MsiPackage MsiPackage1
|
||||
{
|
||||
ProductId = '{DEADBEEF-80C6-41E6-A1B9-8BDB8A05027F}'
|
||||
Path = 'http://Examples/example.msi'
|
||||
Ensure = 'Present'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Uninstalls the MSI file with the product ID: '{DEADBEEF-80C6-41E6-A1B9-8BDB8A05027F}'
|
||||
at the path: 'file://Examples/example.msi'.
|
||||
|
||||
Note that the MSI file with the given product ID must already exist at the specified path.
|
||||
The product ID and path value in this file are provided for example purposes only and will
|
||||
need to be replaced with valid values.
|
||||
|
||||
You can run the following command to get a list of all available MSIs on
|
||||
your system with the correct Path (LocalPackage) and product ID (IdentifyingNumber):
|
||||
|
||||
Get-WmiObject Win32_Product | Format-Table IdentifyingNumber, Name, LocalPackage
|
||||
#>
|
||||
Configuration Sample_MsiPackage_UninstallPackageFromFile
|
||||
{
|
||||
Import-DscResource -ModuleName 'PSDscResources'
|
||||
|
||||
Node localhost
|
||||
{
|
||||
MsiPackage MsiPackage1
|
||||
{
|
||||
ProductId = '{DEADBEEF-80C6-41E6-A1B9-8BDB8A05027F}'
|
||||
Path = 'file://Examples/example.msi'
|
||||
Ensure = 'Absent'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Uninstalls the MSI file with the product ID: '{DEADBEEF-80C6-41E6-A1B9-8BDB8A05027F}'
|
||||
at the path: 'https://Examples/example.msi'.
|
||||
|
||||
Note that the MSI file with the given product ID must already exist on the server.
|
||||
The product ID and path value in this file are provided for example purposes only and will
|
||||
need to be replaced with valid values.
|
||||
#>
|
||||
Configuration Sample_MsiPackage_UninstallPackageFromHttps
|
||||
{
|
||||
Import-DscResource -ModuleName 'PSDscResources'
|
||||
|
||||
Node localhost
|
||||
{
|
||||
MsiPackage MsiPackage1
|
||||
{
|
||||
ProductId = '{DEADBEEF-80C6-41E6-A1B9-8BDB8A05027F}'
|
||||
Path = 'https://Examples/example.msi'
|
||||
Ensure = 'Absent'
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -73,7 +73,7 @@ VariablesToExport = '*'
|
||||
AliasesToExport = @()
|
||||
|
||||
# DSC resources to export from this module
|
||||
DscResourcesToExport = @( 'Archive', 'Environment', 'Group', 'GroupSet', 'Registry', 'Script', 'Service', 'ServiceSet', 'User', 'WindowsFeature', 'WindowsFeatureSet', 'WindowsOptionalFeature', 'WindowsOptionalFeatureSet', 'WindowsPackageCab', 'WindowsProcess', 'ProcessSet' )
|
||||
DscResourcesToExport = @( 'Archive', 'Environment', 'Group', 'GroupSet', 'MsiPackage', 'Registry', 'Script', 'Service', 'ServiceSet', 'User', 'WindowsFeature', 'WindowsFeatureSet', 'WindowsOptionalFeature', 'WindowsOptionalFeatureSet', 'WindowsPackageCab', 'WindowsProcess', 'ProcessSet' )
|
||||
|
||||
# List of all modules packaged with this module
|
||||
# ModuleList = @()
|
||||
|
||||
@@ -41,6 +41,7 @@ Please check out the common DSC Resources [contributing guidelines](https://gith
|
||||
* [Environment](#environment): Provides a mechanism to configure and manage environment variables for a machine or process.
|
||||
* [Group](#group): Provides a mechanism to manage local groups on a target node.
|
||||
* [GroupSet](#groupset): Provides a mechanism to configure and manage multiple Group resources with common settings but different names.
|
||||
* [MsiPackage](#msipackage): Provides a mechanism to install and uninstall MSI packages.
|
||||
* [Registry](#registry): Provides a mechanism to manage registry keys and values on a target node.
|
||||
* [Script](#script): Provides a mechanism to run PowerShell script blocks on a target node.
|
||||
* [Service](#service): Provides a mechanism to configure and manage Windows services on a target node.
|
||||
@@ -177,6 +178,46 @@ None
|
||||
|
||||
* [Add members to multiple groups](https://github.com/PowerShell/PSDscResources/blob/master/Examples/Sample_GroupSet_AddMembers.ps1)
|
||||
|
||||
### MsiPackage
|
||||
|
||||
Provides a mechanism to install and uninstall MSI packages.
|
||||
|
||||
#### Requirements
|
||||
|
||||
None
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **[String] ProductId** _(Key)_: The identifying number used to find the package, usually a GUID.
|
||||
* **[String] Path** _(Required)_: The path to the MSI file that should be installed or uninstalled.
|
||||
* **[String] Ensure** _(Write)_: Specifies whether or not the MSI file should be installed or not. To install the MSI file, specify this property as Present. To uninstall the .msi file, specify this property as Absent. The default value is Present. { *Present* | Absent }.
|
||||
* **[String] Arguments** _(Write)_: The arguments to be passed to the MSI package during installation or uninstallation if needed.
|
||||
* **[System.Management.Automation.PSCredential] Credential** _(Write)_: The credential of a user account to be used to mount a UNC path if needed.
|
||||
* **[String] LogPath** _(Write)_: The path to the log file to log the output from the MSI execution.
|
||||
* **[String] FileHash** _(Write)_: The expected hash value of the MSI file at the given path.
|
||||
* **[String] HashAlgorithm** _(Write)_: The algorithm used to generate the given hash value.
|
||||
* **[String] SignerSubject** _(Write)_: The subject that should match the signer certificate of the digital signature of the MSI file.
|
||||
* **[String] SignerThumbprint** _(Write)_: The certificate thumbprint that should match the signer certificate of the digital signature of the MSI file.
|
||||
* **[String] ServerCertificateValidationCallback** _(Write)_: PowerShell code that should be used to validate SSL certificates for paths using HTTPS.
|
||||
* **[System.Management.Automation.PSCredential] RunAsCredential** _(Write)_: The credential of a user account under which to run the installation or uninstallation of the MSI package.
|
||||
|
||||
#### Read-Only Properties from Get-TargetResource
|
||||
|
||||
* **[String] Name** _(Read)_: The display name of the MSI package.
|
||||
* **[String] InstallSource** _(Read)_: The path to the MSI package.
|
||||
* **[String] InstalledOn** _(Read)_: The date that the MSI package was installed on or serviced on, whichever is later.
|
||||
* **[UInt32] Size** _(Read)_: The size of the MSI package in MB.
|
||||
* **[String] Version** _(Read)_: The version number of the MSI package.
|
||||
* **[String] PackageDescription** _(Read)_: The description of the MSI package.
|
||||
* **[String] Publisher** _(Read)_: The publisher of the MSI package.
|
||||
|
||||
#### Examples
|
||||
|
||||
* [Install the MSI file with the given ID at the given Path](https://github.com/PowerShell/PSDscResources/blob/dev/Examples/Sample_MsiPackage_InstallPackageFromFile.ps1)
|
||||
* [Uninstall the MSI file with the given ID at the given Path](https://github.com/PowerShell/PSDscResources/blob/dev/Examples/Sample_MsiPackage_UninstallPackageFromFile.ps1)
|
||||
* [Install the MSI file with the given ID at the given HTTP URL](https://github.com/PowerShell/PSDscResources/blob/dev/Examples/Sample_MsiPackage_InstallPackageFromHttp.ps1)
|
||||
* [Uninstall the MSI file with the given ID at the given HTTPS URL](https://github.com/PowerShell/PSDscResources/blob/dev/Examples/Sample_MsiPackage_UnstallPackageFromHttps.ps1)
|
||||
|
||||
### Registry
|
||||
|
||||
Provides a mechanism to manage registry keys and values on a target node.
|
||||
@@ -538,6 +579,7 @@ The following parameters will be the same for each process in the set:
|
||||
|
||||
* Archive:
|
||||
* Fixed a minor bug in the unit tests where sometimes the incorrect DateTime format was used.
|
||||
* Added MsiPackage
|
||||
|
||||
### 2.5.0.0
|
||||
|
||||
|
||||
@@ -0,0 +1,643 @@
|
||||
<#
|
||||
Please note that some of these tests depend on each other.
|
||||
They must be run in the order given - if one test fails, subsequent tests may
|
||||
also fail.
|
||||
#>
|
||||
|
||||
$errorActionPreference = 'Stop'
|
||||
Set-StrictMode -Version 'Latest'
|
||||
|
||||
if ($PSVersionTable.PSVersion.Major -lt 5 -or $PSVersionTable.PSVersion.Minor -lt 1)
|
||||
{
|
||||
Write-Warning -Message 'Cannot run PSDscResources integration tests on PowerShell versions lower than 5.1'
|
||||
return
|
||||
}
|
||||
|
||||
Describe 'MsiPackage End to End Tests' {
|
||||
BeforeAll {
|
||||
# Import CommonTestHelper
|
||||
$testsFolderFilePath = Split-Path $PSScriptRoot -Parent
|
||||
$testHelperFolderFilePath = Join-Path -Path $testsFolderFilePath -ChildPath 'TestHelpers'
|
||||
$commonTestHelperFilePath = Join-Path -Path $testHelperFolderFilePath -ChildPath 'CommonTestHelper.psm1'
|
||||
Import-Module -Name $commonTestHelperFilePath
|
||||
|
||||
$script:testEnvironment = Enter-DscResourceTestEnvironment `
|
||||
-DscResourceModuleName 'PSDscResources' `
|
||||
-DscResourceName 'MSFT_MsiPackage' `
|
||||
-TestType 'Integration'
|
||||
|
||||
# Import MsiPackage resource module for Test-TargetResource
|
||||
$moduleRootFilePath = Split-Path -Path $testsFolderFilePath -Parent
|
||||
$dscResourcesFolderFilePath = Join-Path -Path $moduleRootFilePath -ChildPath 'DscResources'
|
||||
$msiPackageResourceFolderFilePath = Join-Path -Path $dscResourcesFolderFilePath -ChildPath 'MSFT_MsiPackage'
|
||||
$msiPackageResourceModuleFilePath = Join-Path -Path $msiPackageResourceFolderFilePath -ChildPath 'MSFT_MsiPackage.psm1'
|
||||
Import-Module -Name $msiPackageResourceModuleFilePath -Force
|
||||
|
||||
# Import the MsiPackage test helper
|
||||
$packageTestHelperFilePath = Join-Path -Path $testHelperFolderFilePath -ChildPath 'MSFT_MsiPackageResource.TestHelper.psm1'
|
||||
Import-Module -Name $packageTestHelperFilePath -Force
|
||||
|
||||
# Set up the paths to the test configurations
|
||||
$script:configurationFilePathNoOptionalParameters = Join-Path -Path $PSScriptRoot -ChildPath 'MSFT_MsiPackage_NoOptionalParameters'
|
||||
$script:configurationFilePathLogPath = Join-Path -Path $PSScriptRoot -ChildPath 'MSFT_MsiPackage_LogPath'
|
||||
|
||||
<#
|
||||
This log file is used to log messages from the mock server which is important for debugging since
|
||||
most of the work of the mock server is done within a separate process.
|
||||
#>
|
||||
$script:logFile = Join-Path -Path $PSScriptRoot -ChildPath 'PackageTestLogFile.txt'
|
||||
$script:environmentInIncorrectStateErrorMessage = 'The current environment is not in the expected state for this test - either something was setup incorrectly on your machine or a previous test failed - results after this may be invalid.'
|
||||
|
||||
$script:msiName = 'DSCSetupProject.msi'
|
||||
$script:msiLocation = Join-Path -Path $TestDrive -ChildPath $script:msiName
|
||||
|
||||
$script:packageId = '{deadbeef-80c6-41e6-a1b9-8bdb8a05027f}'
|
||||
|
||||
$null = New-TestMsi -DestinationPath $script:msiLocation
|
||||
|
||||
# Clear the log file
|
||||
'Beginning integration tests' > $script:logFile
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
# Remove the test MSI if it is still installed
|
||||
if (Test-PackageInstalledById -ProductId $script:packageId)
|
||||
{
|
||||
$null = Start-Process -FilePath 'msiexec.exe' -ArgumentList @("/x$script:packageId", '/passive') -Wait
|
||||
$null = Start-Sleep -Seconds 1
|
||||
}
|
||||
|
||||
if (Test-PackageInstalledById -ProductId $script:packageId)
|
||||
{
|
||||
throw 'Test package could not be uninstalled after running all tests. It may cause errors in subsequent test runs.'
|
||||
}
|
||||
|
||||
Exit-DscResourceTestEnvironment -TestEnvironment $script:testEnvironment
|
||||
}
|
||||
|
||||
Context 'Uninstall package that is already Absent' {
|
||||
$configurationName = 'RemoveAbsentMsiPackage'
|
||||
|
||||
$msiPackageParameters = @{
|
||||
ProductId = $script:packageId
|
||||
Path = $script:msiLocation
|
||||
Ensure = 'Absent'
|
||||
}
|
||||
|
||||
It 'Should return True from Test-TargetResource with the same parameters before configuration' {
|
||||
$testTargetResourceInitialResult = MSFT_MsiPackage\Test-TargetResource @msiPackageParameters
|
||||
$testTargetResourceInitialResult | Should Be $true
|
||||
|
||||
if ($testTargetResourceInitialResult -ne $true)
|
||||
{
|
||||
<#
|
||||
Not throwing an error here since the tests should still run correctly after this,
|
||||
we just want to notify the user that the tests aren't necessarily testing what
|
||||
they should be
|
||||
#>
|
||||
Write-Error -Message $script:environmentInIncorrectStateErrorMessage
|
||||
}
|
||||
}
|
||||
|
||||
It 'Package should not exist on the machine before configuration is run' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $false
|
||||
}
|
||||
|
||||
It 'Should compile and run configuration' {
|
||||
{
|
||||
. $script:configurationFilePathNoOptionalParameters -ConfigurationName $configurationName
|
||||
& $configurationName -OutputPath $TestDrive @msiPackageParameters
|
||||
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
|
||||
} | Should Not Throw
|
||||
}
|
||||
|
||||
It 'Should return True from Test-TargetResource with the same parameters after configuration' {
|
||||
MSFT_MsiPackage\Test-TargetResource @msiPackageParameters | Should Be $true
|
||||
}
|
||||
|
||||
It 'Package should not exist on the machine' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $false
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Install package that is not installed yet' {
|
||||
$configurationName = 'InstallMsiPackage'
|
||||
|
||||
$msiPackageParameters = @{
|
||||
ProductId = $script:packageId
|
||||
Path = $script:msiLocation
|
||||
Ensure = 'Present'
|
||||
}
|
||||
|
||||
It 'Should return False from Test-TargetResource with the same parameters before configuration' {
|
||||
$testTargetResourceInitialResult = MSFT_MsiPackage\Test-TargetResource @msiPackageParameters
|
||||
$testTargetResourceInitialResult | Should Be $false
|
||||
|
||||
if ($testTargetResourceInitialResult -ne $false)
|
||||
{
|
||||
<#
|
||||
Not throwing an error here since the tests should still run correctly after this,
|
||||
we just want to notify the user that the tests aren't necessarily testing what
|
||||
they should be
|
||||
#>
|
||||
Write-Error -Message $script:environmentInIncorrectStateErrorMessage
|
||||
}
|
||||
}
|
||||
|
||||
It 'Package should not exist on the machine before configuration is run' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $false
|
||||
}
|
||||
|
||||
It 'Should compile and run configuration' {
|
||||
{
|
||||
. $script:configurationFilePathNoOptionalParameters -ConfigurationName $configurationName
|
||||
& $configurationName -OutputPath $TestDrive @msiPackageParameters
|
||||
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
|
||||
} | Should Not Throw
|
||||
}
|
||||
|
||||
It 'Should return True from Test-TargetResource with the same parameters after configuration' {
|
||||
MSFT_MsiPackage\Test-TargetResource @msiPackageParameters | Should Be $true
|
||||
}
|
||||
|
||||
It 'Package should exist on the machine' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $true
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Install package that is already installed' {
|
||||
$configurationName = 'InstallExistingMsiPackage'
|
||||
|
||||
$msiPackageParameters = @{
|
||||
ProductId = $script:packageId
|
||||
Path = $script:msiLocation
|
||||
Ensure = 'Present'
|
||||
}
|
||||
|
||||
It 'Should return True from Test-TargetResource with the same parameters before configuration' {
|
||||
$testTargetResourceInitialResult = MSFT_MsiPackage\Test-TargetResource @msiPackageParameters
|
||||
$testTargetResourceInitialResult | Should Be $true
|
||||
|
||||
if ($testTargetResourceInitialResult -ne $true)
|
||||
{
|
||||
<#
|
||||
Not throwing an error here since the tests should still run correctly after this,
|
||||
we just want to notify the user that the tests aren't necessarily testing what
|
||||
they should be
|
||||
#>
|
||||
Write-Error -Message $script:environmentInIncorrectStateErrorMessage
|
||||
}
|
||||
}
|
||||
|
||||
It 'Package should exist on the machine before configuration is run' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $true
|
||||
}
|
||||
|
||||
It 'Should compile and run configuration' {
|
||||
{
|
||||
. $script:configurationFilePathNoOptionalParameters -ConfigurationName $configurationName
|
||||
& $configurationName -OutputPath $TestDrive @msiPackageParameters
|
||||
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
|
||||
} | Should Not Throw
|
||||
}
|
||||
|
||||
It 'Should return True from Test-TargetResource with the same parameters after configuration' {
|
||||
MSFT_MsiPackage\Test-TargetResource @msiPackageParameters | Should Be $true
|
||||
}
|
||||
|
||||
It 'Package should exist on the machine' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $true
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Uninstall package that is installed' {
|
||||
$configurationName = 'UninstallExistingMsiPackage'
|
||||
|
||||
$msiPackageParameters = @{
|
||||
ProductId = $script:packageId
|
||||
Path = $script:msiLocation
|
||||
Ensure = 'Absent'
|
||||
}
|
||||
|
||||
It 'Should return False from Test-TargetResource with the same parameters before configuration' {
|
||||
$testTargetResourceInitialResult = MSFT_MsiPackage\Test-TargetResource @msiPackageParameters
|
||||
$testTargetResourceInitialResult | Should Be $false
|
||||
|
||||
if ($testTargetResourceInitialResult -ne $false)
|
||||
{
|
||||
<#
|
||||
Not throwing an error here since the tests should still run correctly after this,
|
||||
we just want to notify the user that the tests aren't necessarily testing what
|
||||
they should be
|
||||
#>
|
||||
Write-Error -Message $script:environmentInIncorrectStateErrorMessage
|
||||
}
|
||||
}
|
||||
|
||||
It 'Package should exist on the machine before configuration is run' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $true
|
||||
}
|
||||
|
||||
It 'Should compile and run configuration' {
|
||||
{
|
||||
. $script:configurationFilePathNoOptionalParameters -ConfigurationName $configurationName
|
||||
& $configurationName -OutputPath $TestDrive @msiPackageParameters
|
||||
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
|
||||
} | Should Not Throw
|
||||
}
|
||||
|
||||
It 'Should return True from Test-TargetResource with the same parameters after configuration' {
|
||||
MSFT_MsiPackage\Test-TargetResource @msiPackageParameters | Should Be $true
|
||||
}
|
||||
|
||||
It 'Package should not exist on the machine' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $false
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Install package that is not installed and write to specified log file' {
|
||||
$configurationName = 'InstallWithLogFile'
|
||||
|
||||
$logPath = Join-Path -Path $TestDrive -ChildPath 'TestMsiLog.txt'
|
||||
|
||||
if (Test-Path -Path $logPath)
|
||||
{
|
||||
Remove-Item -Path $logPath -Force
|
||||
}
|
||||
|
||||
$msiPackageParameters = @{
|
||||
ProductId = $script:packageId
|
||||
Path = $script:msiLocation
|
||||
Ensure = 'Present'
|
||||
LogPath = $logPath
|
||||
}
|
||||
|
||||
It 'Should return False from Test-TargetResource with the same parameters before configuration' {
|
||||
$testTargetResourceInitialResult = MSFT_MsiPackage\Test-TargetResource @msiPackageParameters
|
||||
$testTargetResourceInitialResult | Should Be $false
|
||||
|
||||
if ($testTargetResourceInitialResult -ne $false)
|
||||
{
|
||||
<#
|
||||
Not throwing an error here since the tests should still run correctly after this,
|
||||
we just want to notify the user that the tests aren't necessarily testing what
|
||||
they should be
|
||||
#>
|
||||
Write-Error -Message $script:environmentInIncorrectStateErrorMessage
|
||||
}
|
||||
}
|
||||
|
||||
It 'Package should not exist on the machine before configuration is run' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $false
|
||||
}
|
||||
|
||||
It 'Should compile and run configuration' {
|
||||
{
|
||||
. $script:configurationFilePathLogPath -ConfigurationName $configurationName
|
||||
& $configurationName -OutputPath $TestDrive @msiPackageParameters
|
||||
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
|
||||
} | Should Not Throw
|
||||
}
|
||||
|
||||
It 'Should return True from Test-TargetResource with the same parameters after configuration' {
|
||||
MSFT_MsiPackage\Test-TargetResource @msiPackageParameters | Should Be $true
|
||||
}
|
||||
|
||||
It 'Should have created the log file' {
|
||||
Test-Path -Path $logPath | Should Be $true
|
||||
}
|
||||
|
||||
It 'Package should exist on the machine' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $true
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Uninstall package that is installed and write to specified log file' {
|
||||
$configurationName = 'InstallWithLogFile'
|
||||
|
||||
$logPath = Join-Path -Path $TestDrive -ChildPath 'TestMsiLog.txt'
|
||||
|
||||
if (Test-Path -Path $logPath)
|
||||
{
|
||||
Remove-Item -Path $logPath -Force
|
||||
}
|
||||
|
||||
$msiPackageParameters = @{
|
||||
ProductId = $script:packageId
|
||||
Path = $script:msiLocation
|
||||
Ensure = 'Absent'
|
||||
LogPath = $logPath
|
||||
}
|
||||
|
||||
It 'Should return False from Test-TargetResource with the same parameters before configuration' {
|
||||
$testTargetResourceInitialResult = MSFT_MsiPackage\Test-TargetResource @msiPackageParameters
|
||||
$testTargetResourceInitialResult | Should Be $false
|
||||
|
||||
if ($testTargetResourceInitialResult -ne $false)
|
||||
{
|
||||
<#
|
||||
Not throwing an error here since the tests should still run correctly after this,
|
||||
we just want to notify the user that the tests aren't necessarily testing what
|
||||
they should be
|
||||
#>
|
||||
Write-Error -Message $script:environmentInIncorrectStateErrorMessage
|
||||
}
|
||||
}
|
||||
|
||||
It 'Package should exist on the machine before configuration is run' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $true
|
||||
}
|
||||
|
||||
It 'Should compile and run configuration' {
|
||||
{
|
||||
. $script:configurationFilePathLogPath -ConfigurationName $configurationName
|
||||
& $configurationName -OutputPath $TestDrive @msiPackageParameters
|
||||
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
|
||||
} | Should Not Throw
|
||||
}
|
||||
|
||||
It 'Should return True from Test-TargetResource with the same parameters after configuration' {
|
||||
MSFT_MsiPackage\Test-TargetResource @msiPackageParameters | Should Be $true
|
||||
}
|
||||
|
||||
It 'Should have created the log file' {
|
||||
Test-Path -Path $logPath | Should Be $true
|
||||
}
|
||||
|
||||
It 'Package should not exist on the machine' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $false
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Install package from HTTP Url' {
|
||||
$configurationName = 'UninstallExistingMsiPackageFromHttp'
|
||||
|
||||
$baseUrl = 'http://localhost:1242/'
|
||||
$msiUrl = "$baseUrl" + 'package.msi'
|
||||
|
||||
$fileServerStarted = $null
|
||||
$job = $null
|
||||
|
||||
$msiPackageParameters = @{
|
||||
ProductId = $script:packageId
|
||||
Path = $msiUrl
|
||||
Ensure = 'Present'
|
||||
}
|
||||
|
||||
It 'Should return False from Test-TargetResource with the same parameters before configuration' {
|
||||
$testTargetResourceInitialResult = MSFT_MsiPackage\Test-TargetResource @msiPackageParameters
|
||||
$testTargetResourceInitialResult | Should Be $false
|
||||
|
||||
if ($testTargetResourceInitialResult -ne $false)
|
||||
{
|
||||
<#
|
||||
Not throwing an error here since the tests should still run correctly after this,
|
||||
we just want to notify the user that the tests aren't necessarily testing what
|
||||
they should be
|
||||
#>
|
||||
Write-Error -Message $script:environmentInIncorrectStateErrorMessage
|
||||
}
|
||||
}
|
||||
|
||||
It 'Package should not exist on the machine before configuration is run' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $false
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$serverResult = Start-Server -FilePath $script:msiLocation -LogPath $script:logFile -Https $false
|
||||
$fileServerStarted = $serverResult.FileServerStarted
|
||||
$job = $serverResult.Job
|
||||
|
||||
$fileServerStarted.WaitOne(30000)
|
||||
|
||||
It 'Should compile and run configuration' {
|
||||
{
|
||||
. $script:configurationFilePathNoOptionalParameters -ConfigurationName $configurationName
|
||||
& $configurationName -OutputPath $TestDrive @msiPackageParameters
|
||||
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
|
||||
} | Should Not Throw
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
<#
|
||||
This must be called after Start-Server to ensure the listening port is closed,
|
||||
otherwise subsequent tests may fail until the machine is rebooted.
|
||||
#>
|
||||
Stop-Server -FileServerStarted $fileServerStarted -Job $job
|
||||
}
|
||||
|
||||
It 'Should return True from Test-TargetResource with the same parameters after configuration' {
|
||||
MSFT_MsiPackage\Test-TargetResource @msiPackageParameters | Should Be $true
|
||||
}
|
||||
|
||||
It 'Package should exist on the machine' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $true
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Uninstall Msi package from HTTP Url' {
|
||||
$configurationName = 'InstallMsiPackageFromHttp'
|
||||
|
||||
$baseUrl = 'http://localhost:1242/'
|
||||
$msiUrl = "$baseUrl" + 'package.msi'
|
||||
|
||||
$fileServerStarted = $null
|
||||
$job = $null
|
||||
|
||||
$msiPackageParameters = @{
|
||||
ProductId = $script:packageId
|
||||
Path = $msiUrl
|
||||
Ensure = 'Absent'
|
||||
}
|
||||
|
||||
It 'Should return False from Test-TargetResource with the same parameters before configuration' {
|
||||
$testTargetResourceInitialResult = MSFT_MsiPackage\Test-TargetResource @msiPackageParameters
|
||||
$testTargetResourceInitialResult | Should Be $false
|
||||
|
||||
if ($testTargetResourceInitialResult -ne $false)
|
||||
{
|
||||
<#
|
||||
Not throwing an error here since the tests should still run correctly after this,
|
||||
we just want to notify the user that the tests aren't necessarily testing what
|
||||
they should be
|
||||
#>
|
||||
Write-Error -Message $script:environmentInIncorrectStateErrorMessage
|
||||
}
|
||||
}
|
||||
|
||||
It 'Package should exist on the machine before configuration is run' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $true
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$serverResult = Start-Server -FilePath $script:msiLocation -LogPath $script:logFile -Https $false
|
||||
$fileServerStarted = $serverResult.FileServerStarted
|
||||
$job = $serverResult.Job
|
||||
|
||||
$fileServerStarted.WaitOne(30000)
|
||||
|
||||
It 'Should compile and run configuration' {
|
||||
{
|
||||
. $script:configurationFilePathNoOptionalParameters -ConfigurationName $configurationName
|
||||
& $configurationName -OutputPath $TestDrive @msiPackageParameters
|
||||
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
|
||||
} | Should Not Throw
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
<#
|
||||
This must be called after Start-Server to ensure the listening port is closed,
|
||||
otherwise subsequent tests may fail until the machine is rebooted.
|
||||
#>
|
||||
Stop-Server -FileServerStarted $fileServerStarted -Job $job
|
||||
}
|
||||
|
||||
It 'Should return true from Test-TargetResource with the same parameters after configuration' {
|
||||
MSFT_MsiPackage\Test-TargetResource @msiPackageParameters | Should Be $true
|
||||
}
|
||||
|
||||
It 'Package should not exist on the machine' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $false
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Install Msi package from HTTPS Url' {
|
||||
$configurationName = 'InstallMsiPackageFromHttpS'
|
||||
|
||||
$baseUrl = 'https://localhost:1243/'
|
||||
$msiUrl = "$baseUrl" + 'package.msi'
|
||||
|
||||
$fileServerStarted = $null
|
||||
$job = $null
|
||||
|
||||
$msiPackageParameters = @{
|
||||
ProductId = $script:packageId
|
||||
Path = $msiUrl
|
||||
Ensure = 'Present'
|
||||
}
|
||||
|
||||
It 'Should return False from Test-TargetResource with the same parameters before configuration' {
|
||||
$testTargetResourceInitialResult = MSFT_MsiPackage\Test-TargetResource @msiPackageParameters
|
||||
$testTargetResourceInitialResult | Should Be $false
|
||||
|
||||
if ($testTargetResourceInitialResult -ne $false)
|
||||
{
|
||||
<#
|
||||
Not throwing an error here since the tests should still run correctly after this,
|
||||
we just want to notify the user that the tests aren't necessarily testing what
|
||||
they should be
|
||||
#>
|
||||
Write-Error -Message $script:environmentInIncorrectStateErrorMessage
|
||||
}
|
||||
}
|
||||
|
||||
It 'Package should not exist on the machine before configuration is run' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $false
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$serverResult = Start-Server -FilePath $script:msiLocation -LogPath $script:logFile -Https $true
|
||||
$fileServerStarted = $serverResult.FileServerStarted
|
||||
$job = $serverResult.Job
|
||||
|
||||
$fileServerStarted.WaitOne(30000)
|
||||
|
||||
It 'Should compile and run configuration' {
|
||||
{
|
||||
. $script:configurationFilePathNoOptionalParameters -ConfigurationName $configurationName
|
||||
& $configurationName -OutputPath $TestDrive @msiPackageParameters
|
||||
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
|
||||
} | Should Not Throw
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
<#
|
||||
This must be called after Start-Server to ensure the listening port is closed,
|
||||
otherwise subsequent tests may fail until the machine is rebooted.
|
||||
#>
|
||||
Stop-Server -FileServerStarted $fileServerStarted -Job $job
|
||||
}
|
||||
|
||||
It 'Should return true from Test-TargetResource with the same parameters after configuration' {
|
||||
MSFT_MsiPackage\Test-TargetResource @msiPackageParameters | Should Be $true
|
||||
}
|
||||
|
||||
It 'Package should exist on the machine' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $true
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Uninstall Msi package from HTTPS Url' {
|
||||
$configurationName = 'UninstallMsiPackageFromHttps'
|
||||
|
||||
$baseUrl = 'https://localhost:1243/'
|
||||
$msiUrl = "$baseUrl" + 'package.msi'
|
||||
|
||||
$fileServerStarted = $null
|
||||
$job = $null
|
||||
|
||||
$msiPackageParameters = @{
|
||||
ProductId = $script:packageId
|
||||
Path = $msiUrl
|
||||
Ensure = 'Absent'
|
||||
}
|
||||
|
||||
It 'Should return False from Test-TargetResource with the same parameters before configuration' {
|
||||
$testTargetResourceInitialResult = MSFT_MsiPackage\Test-TargetResource @msiPackageParameters
|
||||
$testTargetResourceInitialResult | Should Be $false
|
||||
|
||||
if ($testTargetResourceInitialResult -ne $false)
|
||||
{
|
||||
<#
|
||||
Not throwing an error here since the tests should still run correctly after this,
|
||||
we just want to notify the user that the tests aren't necessarily testing what
|
||||
they should be
|
||||
#>
|
||||
Write-Error -Message $script:environmentInIncorrectStateErrorMessage
|
||||
}
|
||||
}
|
||||
|
||||
It 'Package should exist on the machine before configuration is run' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $true
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$serverResult = Start-Server -FilePath $script:msiLocation -LogPath $script:logFile -Https $true
|
||||
$fileServerStarted = $serverResult.FileServerStarted
|
||||
$job = $serverResult.Job
|
||||
|
||||
$fileServerStarted.WaitOne(30000)
|
||||
|
||||
It 'Should compile and run configuration' {
|
||||
{
|
||||
. $script:configurationFilePathNoOptionalParameters -ConfigurationName $configurationName
|
||||
& $configurationName -OutputPath $TestDrive @msiPackageParameters
|
||||
Start-DscConfiguration -Path $TestDrive -ErrorAction 'Stop' -Wait -Force
|
||||
} | Should Not Throw
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
<#
|
||||
This must be called after Start-Server to ensure the listening port is closed,
|
||||
otherwise subsequent tests may fail until the machine is rebooted.
|
||||
#>
|
||||
Stop-Server -FileServerStarted $fileServerStarted -Job $job
|
||||
}
|
||||
|
||||
It 'Should return true from Test-TargetResource with the same parameters after configuration' {
|
||||
MSFT_MsiPackage\Test-TargetResource @msiPackageParameters | Should Be $true
|
||||
}
|
||||
|
||||
It 'Package should not exist on the machine' {
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
$errorActionPreference = 'Stop'
|
||||
Set-StrictMode -Version 'Latest'
|
||||
|
||||
if ($PSVersionTable.PSVersion.Major -lt 5 -or $PSVersionTable.PSVersion.Minor -lt 1)
|
||||
{
|
||||
Write-Warning -Message 'Cannot run PSDscResources integration tests on PowerShell versions lower than 5.1'
|
||||
return
|
||||
}
|
||||
|
||||
$script:testsFolderFilePath = Split-Path $PSScriptRoot -Parent
|
||||
$testHelperFolderFilePath = Join-Path -Path $testsFolderFilePath -ChildPath 'TestHelpers'
|
||||
$commonTestHelperFilePath = Join-Path -Path $testHelperFolderFilePath -ChildPath 'CommonTestHelper.psm1'
|
||||
Import-Module -Name $script:commonTestHelperFilePath
|
||||
|
||||
$script:testEnvironment = Enter-DscResourceTestEnvironment `
|
||||
-DscResourceModuleName 'PSDscResources' `
|
||||
-DscResourceName 'MSFT_MsiPackage' `
|
||||
-TestType 'Unit'
|
||||
|
||||
try
|
||||
{
|
||||
InModuleScope 'MSFT_MsiPackage' {
|
||||
Describe 'MSFT_MsiPackage Integration Tests' {
|
||||
BeforeAll {
|
||||
$testsFolderFilePath = Split-Path $PSScriptRoot -Parent
|
||||
$testHelperFolderFilePath = Join-Path -Path $testsFolderFilePath -ChildPath 'TestHelpers'
|
||||
$commonTestHelperFilePath = Join-Path -Path $testHelperFolderFilePath -ChildPath 'CommonTestHelper.psm1'
|
||||
$packageTestHelperFilePath = Join-Path -Path $testHelperFolderFilePath -ChildPath 'MSFT_MsiPackageResource.TestHelper.psm1'
|
||||
$commonTestHelperFilePath = Join-Path -Path $testHelperFolderFilePath -ChildPath 'CommonTestHelper.psm1'
|
||||
|
||||
Import-Module -Name $packageTestHelperFilePath -Force
|
||||
|
||||
# The common test helper file needs to be imported twice because of the InModuleScope
|
||||
Import-Module -Name $commonTestHelperFilePath
|
||||
|
||||
$script:skipHttpsTest = $false
|
||||
|
||||
<#
|
||||
This log file is used to log messages from the mock server which is important for debugging since
|
||||
most of the work of the mock server is done within a separate process.
|
||||
#>
|
||||
$script:logFile = Join-Path -Path $PSScriptRoot -ChildPath 'PackageTestLogFile.txt'
|
||||
|
||||
$script:msiName = 'DSCSetupProject.msi'
|
||||
$script:msiLocation = Join-Path -Path $TestDrive -ChildPath $script:msiName
|
||||
$script:msiArguments = '/NoReboot'
|
||||
|
||||
$script:packageId = '{deadbeef-80c6-41e6-a1b9-8bdb8a05027f}'
|
||||
|
||||
$null = New-TestMsi -DestinationPath $script:msiLocation
|
||||
|
||||
# Clear the log file
|
||||
'Beginning integration tests' > $script:logFile
|
||||
}
|
||||
|
||||
BeforeEach {
|
||||
if (Test-PackageInstalledById -ProductId $script:packageId)
|
||||
{
|
||||
$null = Start-Process -FilePath 'msiexec.exe' -ArgumentList @("/x$script:packageId", '/passive') -Wait
|
||||
$null = Start-Sleep -Seconds 1
|
||||
}
|
||||
|
||||
if (Test-PackageInstalledById -ProductId $script:packageId)
|
||||
{
|
||||
throw 'Test package could not be uninstalled after running all tests. It may cause errors in subsequent test runs.'
|
||||
}
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
if (Test-PackageInstalledById -ProductId $script:packageId)
|
||||
{
|
||||
$null = Start-Process -FilePath 'msiexec.exe' -ArgumentList @("/x$script:packageId", '/passive') -Wait
|
||||
$null = Start-Sleep -Seconds 1
|
||||
}
|
||||
|
||||
if (Test-PackageInstalledById -ProductId $script:packageId)
|
||||
{
|
||||
throw 'Test package could not be uninstalled after running test'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Get-TargetResource' {
|
||||
It 'Should return only basic properties for absent package' {
|
||||
$packageParameters = @{
|
||||
Path = $script:msiLocation
|
||||
ProductId = $script:packageId
|
||||
}
|
||||
|
||||
$getTargetResourceResult = Get-TargetResource @packageParameters
|
||||
$getTargetResourceResultProperties = @( 'Ensure', 'ProductId' )
|
||||
|
||||
Test-GetTargetResourceResult -GetTargetResourceResult $getTargetResourceResult -GetTargetResourceResultProperties $getTargetResourceResultProperties
|
||||
}
|
||||
|
||||
It 'Should return full package properties for present package without registry check parameters specified' {
|
||||
$packageParameters = @{
|
||||
Path = $script:msiLocation
|
||||
ProductId = $script:packageId
|
||||
}
|
||||
|
||||
Set-TargetResource -Ensure 'Present' @packageParameters
|
||||
|
||||
$getTargetResourceResult = Get-TargetResource @packageParameters
|
||||
$getTargetResourceResultProperties = @( 'Ensure', 'Name', 'InstallSource', 'InstalledOn', 'ProductId', 'Size', 'Version', 'PackageDescription', 'Publisher' )
|
||||
|
||||
Test-GetTargetResourceResult -GetTargetResourceResult $getTargetResourceResult -GetTargetResourceResultProperties $getTargetResourceResultProperties
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Test-TargetResource' {
|
||||
It 'Should return correct value when package is absent' {
|
||||
$testTargetResourceResult = Test-TargetResource `
|
||||
-Ensure 'Present' `
|
||||
-Path $script:msiLocation `
|
||||
-ProductId $script:packageId
|
||||
|
||||
$testTargetResourceResult | Should Be $false
|
||||
|
||||
$testTargetResourceResult = Test-TargetResource `
|
||||
-Ensure 'Absent' `
|
||||
-Path $script:msiLocation `
|
||||
-ProductId $script:packageId
|
||||
|
||||
$testTargetResourceResult | Should Be $true
|
||||
}
|
||||
|
||||
It 'Should return correct value when package is present' {
|
||||
Set-TargetResource -Ensure 'Present' -Path $script:msiLocation -ProductId $script:packageId
|
||||
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $true
|
||||
|
||||
$testTargetResourceResult = Test-TargetResource `
|
||||
-Ensure 'Present' `
|
||||
-Path $script:msiLocation `
|
||||
-ProductId $script:packageId `
|
||||
|
||||
$testTargetResourceResult | Should Be $true
|
||||
|
||||
$testTargetResourceResult = Test-TargetResource `
|
||||
-Ensure 'Absent' `
|
||||
-Path $script:msiLocation `
|
||||
-ProductId $script:packageId `
|
||||
|
||||
$testTargetResourceResult | Should Be $false
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Set-TargetResource' {
|
||||
It 'Should correctly install and remove a .msi package' {
|
||||
Set-TargetResource -Ensure 'Present' -Path $script:msiLocation -ProductId $script:packageId
|
||||
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $true
|
||||
|
||||
$getTargetResourceResult = Get-TargetResource -Path $script:msiLocation -ProductId $script:packageId
|
||||
|
||||
$getTargetResourceResult.Version | Should Be '1.2.3.4'
|
||||
$getTargetResourceResult.InstalledOn | Should Be ('{0:d}' -f [DateTime]::Now.Date)
|
||||
$getTargetResourceResult.ProductId | Should Be $script:packageId
|
||||
|
||||
[Math]::Round($getTargetResourceResult.Size, 2) | Should Be 0.03
|
||||
|
||||
Set-TargetResource -Ensure 'Absent' -Path $script:msiLocation -ProductId $script:packageId
|
||||
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $false
|
||||
}
|
||||
|
||||
It 'Should throw with incorrect product id' {
|
||||
$wrongPackageId = '{deadbeef-80c6-41e6-a1b9-8bdb8a050272}'
|
||||
|
||||
{ Set-TargetResource -Ensure 'Present' -Path $script:msiLocation -ProductId $wrongPackageId } | Should Throw
|
||||
}
|
||||
|
||||
It 'Should correctly install and remove a package from a HTTP URL' {
|
||||
$baseUrl = 'http://localhost:1242/'
|
||||
$msiUrl = "$baseUrl" + 'package.msi'
|
||||
|
||||
$fileServerStarted = $null
|
||||
$job = $null
|
||||
|
||||
try
|
||||
{
|
||||
'Http tests:' >> $script:logFile
|
||||
|
||||
$serverResult = Start-Server -FilePath $script:msiLocation -LogPath $script:logFile -Https $false
|
||||
$fileServerStarted = $serverResult.FileServerStarted
|
||||
$job = $serverResult.Job
|
||||
|
||||
# Wait for the file server to be ready to receive requests
|
||||
$fileServerStarted.WaitOne(30000)
|
||||
|
||||
{ Set-TargetResource -Ensure 'Present' -Path $baseUrl -ProductId $script:packageId } | Should Throw
|
||||
|
||||
Set-TargetResource -Ensure 'Present' -Path $msiUrl -ProductId $script:packageId
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $true
|
||||
|
||||
Set-TargetResource -Ensure 'Absent' -Path $msiUrl -ProductId $script:packageId
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $false
|
||||
}
|
||||
finally
|
||||
{
|
||||
<#
|
||||
This must be called after Start-Server to ensure the listening port is closed,
|
||||
otherwise subsequent tests may fail until the machine is rebooted.
|
||||
#>
|
||||
Stop-Server -FileServerStarted $fileServerStarted -Job $job
|
||||
}
|
||||
}
|
||||
|
||||
It 'Should correctly install and remove a package from a HTTPS URL' -Skip:$script:skipHttpsTest {
|
||||
|
||||
$baseUrl = 'https://localhost:1243/'
|
||||
$msiUrl = "$baseUrl" + 'package.msi'
|
||||
|
||||
$fileServerStarted = $null
|
||||
$job = $null
|
||||
|
||||
try
|
||||
{
|
||||
'Https tests:' >> $script:logFile
|
||||
|
||||
$serverResult = Start-Server -FilePath $script:msiLocation -LogPath $script:logFile -Https $true
|
||||
$fileServerStarted = $serverResult.FileServerStarted
|
||||
$job = $serverResult.Job
|
||||
|
||||
# Wait for the file server to be ready to receive requests
|
||||
$fileServerStarted.WaitOne(30000)
|
||||
|
||||
{ Set-TargetResource -Ensure 'Present' -Path $baseUrl -ProductId $script:packageId } | Should Throw
|
||||
|
||||
Set-TargetResource -Ensure 'Present' -Path $msiUrl -ProductId $script:packageId
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $true
|
||||
|
||||
Set-TargetResource -Ensure 'Absent' -Path $msiUrl -ProductId $script:packageId
|
||||
Test-PackageInstalledById -ProductId $script:packageId | Should Be $false
|
||||
}
|
||||
finally
|
||||
{
|
||||
<#
|
||||
This must be called after Start-Server to ensure the listening port is closed,
|
||||
otherwise subsequent tests may fail until the machine is rebooted.
|
||||
#>
|
||||
Stop-Server -FileServerStarted $fileServerStarted -Job $job
|
||||
}
|
||||
}
|
||||
|
||||
It 'Should write to the specified log path' {
|
||||
$logPath = Join-Path -Path $TestDrive -ChildPath 'TestMsiLog.txt'
|
||||
|
||||
if (Test-Path -Path $logPath)
|
||||
{
|
||||
Remove-Item -Path $logPath -Force
|
||||
}
|
||||
|
||||
Set-TargetResource -Ensure 'Present' -Path $script:msiLocation -LogPath $logPath -ProductId $script:packageId
|
||||
|
||||
Test-Path -Path $logPath | Should Be $true
|
||||
Get-Content -Path $logPath | Should Not Be $null
|
||||
}
|
||||
|
||||
It 'Should add space after .MSI installation arguments' {
|
||||
Mock Invoke-Process -ParameterFilter { $Process.StartInfo.Arguments.EndsWith($script:msiArguments) } { return @{ ExitCode = 0 } }
|
||||
Mock Get-ProductEntry { return $script:packageId }
|
||||
|
||||
$packageParameters = @{
|
||||
Path = $script:msiLocation
|
||||
ProductId = $script:packageId
|
||||
Arguments = $script:msiArguments
|
||||
}
|
||||
|
||||
Set-TargetResource -Ensure 'Present' @packageParameters
|
||||
|
||||
Assert-MockCalled Invoke-Process -ParameterFilter { $Process.StartInfo.Arguments.EndsWith(" $script:msiArguments") } -Scope It
|
||||
}
|
||||
|
||||
It 'Should not check for product installation when rebooted is required' {
|
||||
Mock Invoke-Process { return 3010 }
|
||||
Mock Get-ProductEntry { }
|
||||
|
||||
$packageParameters = @{
|
||||
Path = $script:msiLocation
|
||||
ProductId = $script:packageId
|
||||
}
|
||||
|
||||
{ Set-TargetResource -Ensure 'Present' @packageParameters } | Should Not Throw
|
||||
}
|
||||
|
||||
It 'Should install package using user credentials when specified' {
|
||||
Mock Invoke-PInvoke { }
|
||||
Mock Get-ProductEntry { return $script:packageId }
|
||||
|
||||
$packageCredential = [System.Management.Automation.PSCredential]::Empty
|
||||
$packageParameters = @{
|
||||
Path = $script:msiLocation
|
||||
ProductId = $script:packageId
|
||||
RunAsCredential = $packageCredential
|
||||
}
|
||||
|
||||
Set-TargetResource -Ensure 'Present' @packageParameters
|
||||
|
||||
Assert-MockCalled Invoke-PInvoke -ParameterFilter { $RunAsCredential -eq $packageCredential} -Scope It
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Exit-DscResourceTestEnvironment -TestEnvironment $script:testEnvironment
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[String]
|
||||
$ConfigurationName
|
||||
)
|
||||
|
||||
Configuration $ConfigurationName
|
||||
{
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String]
|
||||
$ProductId,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String]
|
||||
$Path,
|
||||
|
||||
[ValidateSet('Present', 'Absent')]
|
||||
[String]
|
||||
$Ensure = 'Present',
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[String]
|
||||
$LogPath
|
||||
)
|
||||
|
||||
Import-DscResource -ModuleName 'PSDscResources'
|
||||
|
||||
Node localhost
|
||||
{
|
||||
MsiPackage MsiPackage1
|
||||
{
|
||||
ProductId = $ProductId
|
||||
Path = $Path
|
||||
Ensure = $Ensure
|
||||
LogPath = $LogPath
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[String]
|
||||
$ConfigurationName
|
||||
)
|
||||
|
||||
Configuration $ConfigurationName
|
||||
{
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String]
|
||||
$ProductId,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String]
|
||||
$Path,
|
||||
|
||||
[ValidateSet('Present', 'Absent')]
|
||||
[String]
|
||||
$Ensure = 'Present'
|
||||
)
|
||||
|
||||
Import-DscResource -ModuleName 'PSDscResources'
|
||||
|
||||
Node localhost
|
||||
{
|
||||
MsiPackage MsiPackage1
|
||||
{
|
||||
ProductId = $ProductId
|
||||
Path = $Path
|
||||
Ensure = $Ensure
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,386 @@ Set-StrictMode -Version 'Latest'
|
||||
#>
|
||||
$script:appVeyorAdministratorCredential = $null
|
||||
|
||||
<#
|
||||
String data for unit test names to be used with the generic test functions.
|
||||
Maps command names to the appropriate test names to insert when checking that
|
||||
the correct mocks are called.
|
||||
In the future we will move this data out of the commonTestHelper file and into the
|
||||
corresponding test file or its own file. For now, it is much easier to access this
|
||||
way rather than passing it around.
|
||||
#>
|
||||
data testStrings
|
||||
{
|
||||
ConvertFrom-StringData -StringData @'
|
||||
Assert-FileHashValid = assert that the file hash is valid
|
||||
Assert-FileSignatureValid = assert that the file signature is valid
|
||||
Assert-FileValid = assert that the file is valid
|
||||
Assert-PathExtensionValid = assert that the specified path extension is valid
|
||||
Close-Stream = close the stream
|
||||
Convert-PathToUri = convert the path to a URI
|
||||
Convert-ProductIdToIdentifyingNumber = convert the product ID to the identifying number
|
||||
Copy-ResponseStreamToFileStream = copy the response to the outstream
|
||||
Get-ItemProperty = retrieve {0}
|
||||
Get-MsiProductCode = retrieve the MSI product code
|
||||
Get-ProductEntry = retrieve the product entry
|
||||
Get-ProductEntryInfo = retrieve the product entry info
|
||||
Get-ProductEntryValue = retrieve the value of the product entry property
|
||||
Get-ScriptBlock = retrieve the script block
|
||||
Get-WebRequest = retrieve the WebRequest object
|
||||
Get-WebRequestResponse = retrieve the web request response
|
||||
Get-WebRequestResponseStream = retrieve the WebRequest response stream
|
||||
Invoke-CimMethod = attempt to invoke a cim method to check if reboot is required
|
||||
Invoke-PInvoke = attempt to {0} the MSI package under the user
|
||||
Invoke-Process = attempt to {0} the MSI package under the process
|
||||
New-Item = create a new {0}
|
||||
New-LogFile = create a new log file
|
||||
New-Object = create a new {0}
|
||||
New-PSDrive = create a new PS Drive
|
||||
Remove-Item = remove {0}
|
||||
Remove-PSDrive = remove the PS drive
|
||||
Start-MsiProcess = start the MSI process
|
||||
Test-Path = test that the path {0} exists
|
||||
'@
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieves the name of the test for asserting that the given function is called.
|
||||
|
||||
.PARAMETER IsCalled
|
||||
Indicates whether the function should be called or not.
|
||||
|
||||
.PARAMETER Custom
|
||||
An optional string to include in the test name to make the name more descriptive.
|
||||
Can only be used by commands that have a variable in their string data name.
|
||||
#>
|
||||
function Get-TestName
|
||||
{
|
||||
[OutputType([String])]
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[String]
|
||||
$Command,
|
||||
|
||||
[Boolean]
|
||||
$IsCalled = $true,
|
||||
|
||||
[String]
|
||||
$Custom = ''
|
||||
)
|
||||
|
||||
$testName = ''
|
||||
|
||||
if (-not [String]::IsNullOrEmpty($Custom))
|
||||
{
|
||||
$testName = ($testStrings.$Command -f $Custom)
|
||||
}
|
||||
else
|
||||
{
|
||||
$testName = $testStrings.$Command
|
||||
}
|
||||
|
||||
if ($IsCalled)
|
||||
{
|
||||
return 'Should ' + $testName
|
||||
}
|
||||
else
|
||||
{
|
||||
return 'Should not ' + $testName
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Tests that each mock in MocksCalled is called the expected number of times.
|
||||
|
||||
.PARAMETER MocksCalled
|
||||
An array of the mocked commands that should be called or not called.
|
||||
Each item in the array is a hashtable that contains the name of the command
|
||||
being mocked and the number of times it is called (can be 0).
|
||||
#>
|
||||
function Invoke-ExpectedMocksAreCalledTest
|
||||
{
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Hashtable[]]
|
||||
$MocksCalled
|
||||
)
|
||||
|
||||
foreach ($mock in $MocksCalled)
|
||||
{
|
||||
$testName = Get-TestName -Command $mock.Command -IsCalled $mock.Times
|
||||
|
||||
if ($mock.Keys -contains 'Custom')
|
||||
{
|
||||
$testName = Get-TestName -Command $mock.Command -IsCalled $mock.Times -Custom $mock.Custom
|
||||
}
|
||||
|
||||
It $testName {
|
||||
Assert-MockCalled -CommandName $mock.Command -Exactly $mock.Times -Scope 'Context'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Performs generic tests for the given function, including checking that the
|
||||
function does not throw and checking that all mocks are called the expected
|
||||
number of times.
|
||||
|
||||
.PARAMETER Function
|
||||
The function to be called. Must be in format:
|
||||
{ Param($hashTableOfParamsToPass) Function-Name @hashTableOfParamsToPass }
|
||||
For example:
|
||||
{ Param($testLogPath) New-LogFile $script:testPath }
|
||||
or
|
||||
{ Param($startMsiProcessParameters) Start-MsiProcess @startMsiProcessParameters }
|
||||
|
||||
.PARAMETER FunctionParameters
|
||||
The parameters that should be passed to the function for this test. Should match
|
||||
what is passed in the Function parameter.
|
||||
|
||||
.PARAMETER MocksCalled
|
||||
An array of the mocked commands that should be called for this test.
|
||||
Each item in the array is a hashtable that contains the name of the command
|
||||
being mocked, the number of times it is called (can be 0) and, optionally,
|
||||
an extra custom string to make the test name more descriptive. The custom
|
||||
string will only work if the command has a corresponding variable in the
|
||||
string data name.
|
||||
|
||||
.PARAMETER ShouldThrow
|
||||
Indicates whether the function should throw or not. If this is set to True
|
||||
then ErrorMessage and ErrorTestName should also be passed.
|
||||
|
||||
.PARAMETER ErrorMessage
|
||||
The error message that should be thrown if the function is supposed to throw.
|
||||
|
||||
.PARAMETER ErrorTestName
|
||||
The string that should be used to create the name of the test that checks for
|
||||
the correct error being thrown.
|
||||
#>
|
||||
function Invoke-GenericUnitTest {
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ScriptBlock]
|
||||
$Function,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Hashtable]
|
||||
$FunctionParameters,
|
||||
|
||||
[Hashtable[]]
|
||||
$MocksCalled,
|
||||
|
||||
[Boolean]
|
||||
$ShouldThrow = $false,
|
||||
|
||||
[String]
|
||||
$ErrorMessage = '',
|
||||
|
||||
[String]
|
||||
$ErrorTestName = ''
|
||||
)
|
||||
|
||||
if ($ShouldThrow)
|
||||
{
|
||||
It "Should throw an error for $ErrorTestName" {
|
||||
{ $null = $($Function.Invoke($FunctionParameters)) } | Should Throw $ErrorMessage
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
It 'Should not throw' {
|
||||
{ $null = $($Function.Invoke($FunctionParameters)) } | Should Not Throw
|
||||
}
|
||||
}
|
||||
|
||||
Invoke-ExpectedMocksAreCalledTest -MocksCalled $MocksCalled
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Performs generic tests for Get-TargetResource, including checking that the
|
||||
function does not throw, checking that all mocks are called the expected
|
||||
number of times, and checking that the correct result is returned. If the function
|
||||
is expected to throw, then this function should not be used.
|
||||
|
||||
.PARAMETER GetTargetResourceParameters
|
||||
The parameters that should be passed to Get-TargetResource for this test.
|
||||
|
||||
.PARAMETER MocksCalled
|
||||
An array of the mocked commands that should be called for this test.
|
||||
Each item in the array is a hashtable that contains the name of the command
|
||||
being mocked, the number of times it is called (can be 0) and, optionally,
|
||||
an extra custom string to make the test name more descriptive. The custom
|
||||
string will only work if the command has a corresponding variable in the
|
||||
string data name.
|
||||
|
||||
.PARAMETER ExpectedReturnValue
|
||||
The expected hashtable that Get-TargetResource should return for this test.
|
||||
#>
|
||||
function Invoke-GetTargetResourceUnitTest
|
||||
{
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Hashtable]
|
||||
$GetTargetResourceParameters,
|
||||
|
||||
[Hashtable[]]
|
||||
$MocksCalled,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Hashtable]
|
||||
$ExpectedReturnValue
|
||||
)
|
||||
|
||||
It 'Should not throw' {
|
||||
{ $null = Get-TargetResource @GetTargetResourceParameters } | Should Not Throw
|
||||
}
|
||||
|
||||
Invoke-ExpectedMocksAreCalledTest -MocksCalled $MocksCalled
|
||||
|
||||
$getTargetResourceResult = Get-TargetResource @GetTargetResourceParameters
|
||||
|
||||
It 'Should return a Hashtable' {
|
||||
$getTargetResourceResult -is [Hashtable] | Should Be $true
|
||||
}
|
||||
|
||||
It "Should return a Hashtable with $($ExpectedReturnValue.Keys.Count) properties" {
|
||||
$getTargetResourceResult.Keys.Count | Should Be $ExpectedReturnValue.Keys.Count
|
||||
}
|
||||
|
||||
foreach ($key in $ExpectedReturnValue.Keys)
|
||||
{
|
||||
It "Should return a Hashtable with the $key property as $($ExpectedReturnValue.$key)" {
|
||||
$getTargetResourceResult.$key | Should Be $ExpectedReturnValue.$key
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Performs generic tests for Set-TargetResource, including checking that the
|
||||
function does not throw and checking that all mocks are called the expected
|
||||
number of times.
|
||||
|
||||
.PARAMETER SetTargetResourceParameters
|
||||
The parameters that should be passed to Set-TargetResource for this test.
|
||||
|
||||
.PARAMETER MocksCalled
|
||||
An array of the mocked commands that should be called for this test.
|
||||
Each item in the array is a hashtable that contains the name of the command
|
||||
being mocked, the number of times it is called (can be 0) and, optionally,
|
||||
an extra custom string to make the test name more descriptive. The custom
|
||||
string will only work if the command has a corresponding variable in the
|
||||
string data name.
|
||||
|
||||
.PARAMETER ShouldThrow
|
||||
Indicates whether Set-TargetResource should throw or not. If this is set to True
|
||||
then ErrorMessage and ErrorTestName should also be passed.
|
||||
|
||||
.PARAMETER ErrorMessage
|
||||
The error message that should be thrown if Set-TargetResource is supposed to throw.
|
||||
|
||||
.PARAMETER ErrorTestName
|
||||
The string that should be used to create the name of the test that checks for
|
||||
the correct error being thrown.
|
||||
#>
|
||||
function Invoke-SetTargetResourceUnitTest {
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Hashtable]
|
||||
$SetTargetResourceParameters,
|
||||
|
||||
[Hashtable[]]
|
||||
$MocksCalled,
|
||||
|
||||
[Boolean]
|
||||
$ShouldThrow = $false,
|
||||
|
||||
[String]
|
||||
$ErrorMessage = '',
|
||||
|
||||
[String]
|
||||
$ErrorTestName = ''
|
||||
)
|
||||
|
||||
if ($ShouldThrow)
|
||||
{
|
||||
It "Should throw an error for $ErrorTestName" {
|
||||
{ $null = Set-TargetResource @SetTargetResourceParameters } | Should Throw $ErrorMessage
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
It 'Should not throw' {
|
||||
{ $null = Set-TargetResource @SetTargetResourceParameters } | Should Not Throw
|
||||
}
|
||||
}
|
||||
|
||||
Invoke-ExpectedMocksAreCalledTest -MocksCalled $MocksCalled
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Performs generic tests for Test-TargetResource, including checking that the
|
||||
function does not throw, checking that all mocks are called the expected
|
||||
number of times, and checking that the correct result is returned. If the function
|
||||
is expected to throw, then this function should not be used.
|
||||
|
||||
.PARAMETER TestTargetResourceParameters
|
||||
The parameters that should be passed to Test-TargetResource for this test.
|
||||
|
||||
.PARAMETER MocksCalled
|
||||
An array of the mocked commands that should be called for this test.
|
||||
Each item in the array is a hashtable that contains the name of the command
|
||||
being mocked, the number of times it is called (can be 0) and, optionally,
|
||||
an extra custom string to make the test name more descriptive. The custom
|
||||
string will only work if the command has a corresponding variable in the
|
||||
string data name.
|
||||
|
||||
.PARAMETER ExpectedReturnValue
|
||||
The expected boolean value that should be returned
|
||||
#>
|
||||
function Invoke-TestTargetResourceUnitTest
|
||||
{
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Hashtable]
|
||||
$TestTargetResourceParameters,
|
||||
|
||||
[Hashtable[]]
|
||||
$MocksCalled,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Boolean]
|
||||
$ExpectedReturnValue
|
||||
)
|
||||
|
||||
It 'Should not throw' {
|
||||
{ $null = Test-TargetResource @TestTargetResourceParameters } | Should Not Throw
|
||||
}
|
||||
|
||||
Invoke-ExpectedMocksAreCalledTest -MocksCalled $MocksCalled
|
||||
|
||||
$testTargetResourceResult = Test-TargetResource @TestTargetResourceParameters
|
||||
|
||||
It "Should return $ExpectedReturnValue" {
|
||||
$testTargetResourceResult | Should Be $ExpectedReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Tests that the Get-TargetResource method of a DSC Resource is not null, can be converted to a hashtable, and has the correct properties.
|
||||
@@ -417,5 +797,10 @@ Export-ModuleMember -Function @(
|
||||
'Test-SetTargetResourceWithWhatIf', `
|
||||
'Get-AppVeyorAdministratorCredential', `
|
||||
'Enter-DscResourceTestEnvironment', `
|
||||
'Exit-DscResourceTestEnvironment'
|
||||
'Exit-DscResourceTestEnvironment', `
|
||||
'Invoke-GetTargetResourceUnitTest', `
|
||||
'Invoke-SetTargetResourceUnitTest', `
|
||||
'Invoke-TestTargetResourceUnitTest', `
|
||||
'Invoke-ExpectedMocksAreCalledTest', `
|
||||
'Invoke-GenericUnitTest'
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user