PowerShell/test/powershell/engine/Module/ModuleSpecification.Tests.ps1

263 lines
8.8 KiB
PowerShell

# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
using namespace Microsoft.PowerShell.Commands
# Take a hashtable and return two copies,
# one with the key/value pair, the other without
function PermuteHashtableOnProperty
{
param([hashtable[]]$Hashtable, [string]$Key, [object]$Value)
foreach ($ht in $Hashtable)
{
$ht.Clone()
}
foreach ($ht in $Hashtable)
{
$ht2 = $ht.Clone()
$ht2.$Key = $Value
$ht2
}
}
# Take a base hashtable and produce all possible
# combinations of that hashtable with the keys
# and values in the key/value hashtable
function PermuteHashtable
{
param([hashtable]$InitialTable, [hashtable]$KeyValues)
$l = $InitialTable
foreach ($key in $KeyValues.Keys)
{
$l = PermuteHashtableOnProperty -Hashtable $l -Key $key -Value $KeyValues[$key]
}
$l
}
$guid = [guid]::NewGuid()
$modSpecRequired = @{
ModuleName = "ModSpecRequired"
RequiredVersion = "3.0.2"
}
$requiredOptionalConstraints = @{ Guid = $guid }
$modSpecRange = @{
ModuleName = "ModSpecRequired"
ModuleVersion = "3.0.1"
}
$rangeOptionalConstraints = @{ MaximumVersion = "3.2.0"; Guid = $guid }
Describe "ModuleSpecification objects and logic" -Tag "CI" {
BeforeAll {
$testCases = [System.Collections.Generic.List[hashtable]]::new()
foreach ($case in (PermuteHashtable -InitialTable $modSpecRequired -KeyValues $requiredOptionalConstraints))
{
$testCases.Add(@{
ModuleSpecification = $case
Keys = ($case.Keys -join ",")
})
}
foreach ($case in (PermuteHashtable -InitialTable $modSpecRange -KeyValues $rangeOptionalConstraints))
{
$testCases.Add(@{
ModuleSpecification = $case
Keys = ($case.Keys -join ",")
})
}
$testCases = $testCases.ToArray()
}
Context "ModuleSpecification construction and string parsing" {
BeforeAll {
$differentFieldCases = @(
@{
TestName = "Guid"
ModSpec1 = @{ Guid = [guid]::NewGuid(); ModuleName = "TestModule"; ModuleVersion = "1.0" }
ModSpec2 = @{ Guid = [guid]::NewGuid(); ModuleName = "TestModule"; ModuleVersion = "1.0" }
},
@{
TestName = "RequiredVersion"
ModSpec1 = @{ ModuleName = "Module"; RequiredVersion = "3.0" }
ModSpec2 = @{ ModuleName = "Module"; RequiredVersion = "3.1" }
},
@{
TestName = "Version/MaxVersion-present"
ModSpec1 = @{ ModuleName = "ThirdModule"; ModuleVersion = "2.1" }
ModSpec2 = @{ ModuleName = "ThirdModule"; MaximumVersion = "2.1" }
},
@{
TestName = "RequiredVersion/Version-present"
ModSpec1 = @{ ModuleName = "FourthModule"; RequiredVersion = "3.0" }
ModSpec2 = @{ ModuleName = "FourthModule"; ModuleVersion = "3.0" }
}
)
}
It "Can be created from a name" {
$ms = [ModuleSpecification]::new("NamedModule")
$ms | Should -Not -BeNull
$ms.Name | Should -BeExactly "NamedModule"
}
It "Can be created from Hashtable with keys: <Keys>" -TestCases $testCases {
param([hashtable]$ModuleSpecification, [string]$Keys)
$ms = [ModuleSpecification]::new($ModuleSpecification)
$ms.Name | Should -BeExactly $ModuleSpecification.ModuleName
if ($ModuleSpecification.Guid)
{
$ms.Guid | Should -Be $ModuleSpecification.Guid
}
if ($ModuleSpecification.ModuleVersion)
{
$ms.Version | Should -Be $ModuleSpecification.ModuleVersion
}
if ($ModuleSpecification.RequiredVersion)
{
$ms.RequiredVersion | Should -Be $ModuleSpecification.RequiredVersion
}
if ($ModuleSpecification.MaximumVersion)
{
$ms.MaximumVersion | Should -Be $ModuleSpecification.MaximumVersion
}
}
It "Can be reconstructed from self.ToString() with keys: <Keys>" -TestCases $testCases {
param([hashtable]$ModuleSpecification, [string]$Keys)
$ms = [ModuleSpecification]::new($ModuleSpecification)
[ModuleSpecification]$clone = $null
[ModuleSpecification]::TryParse(($ms.ToString()), [ref]$clone) | Should -BeTrue
$clone.Name | Should -Be $ModuleSpecification.ModuleName
if ($ModuleSpecification.RequiredVersion)
{
$clone.RequiredVersion | Should -Be $ModuleSpecification.RequiredVersion
}
if ($ModuleSpecification.Version)
{
$clone.Version | Should -Be $ModuleSpecification.Version
}
if ($ModuleSpecification.MaximumVersion)
{
$clone.MaximumVersion | Should -Be $ModuleSpecification.MaximumVersion
}
if ($ModuleSpecification.Guid)
{
$clone.Guid | Should -Be $ModuleSpecification.Guid
}
}
}
Context "ModuleSpecification comparison" {
BeforeAll {
$modSpecAsm = [ModuleSpecification].Assembly
$modSpecComparerType = $modSpecAsm.GetType("Microsoft.PowerShell.Commands.ModuleSpecificationComparer")
$comparer = [System.Activator]::CreateInstance($modSpecComparerType)
}
It "Module specifications with same fields <Keys> are equal" -TestCases $testCases {
param([hashtable]$ModuleSpecification, [string]$Keys)
$ms = [ModuleSpecification]::new($ModuleSpecification)
$ms2 = [ModuleSpecification]::new($ModuleSpecification)
$comparer.Equals($ms, $ms2) | Should -BeTrue
}
It "Module specifications with same fields <Keys> have the same hash code" -TestCases $testCases {
param([hashtable]$ModuleSpecification, [string]$Keys)
$ms = [ModuleSpecification]::new($ModuleSpecification)
$ms2 = [ModuleSpecification]::new($ModuleSpecification)
$comparer.GetHashCode($ms) | Should -Be $comparer.GetHashCode($ms2)
}
It "Module specifications with different <TestName> fields are not equal" -TestCases $differentFieldCases {
param($TestName, $ModSpec1, $ModSpec2)
$ms1 = [ModuleSpecification]::new($ModSpec1)
$ms2 = [ModuleSpecification]::new($ModSpec2)
$comparer.Equals($ms1, $ms2) | Should -BeFalse
}
It "Compares two null module specifications as equal" {
$comparer.Equals($null, $null) | Should -BeTrue
}
It "Compares a null module specification with another as unequal" {
$ms = [ModuleSpecification]::new(@{
MOduleName = "NonNullModule"
Guid = [guid]::NewGuid()
RequiredVersion = "3.2.1"
})
$comparer.Equals($ms, $null) | Should -BeFalse
}
It "Succeeds to get a hash code from a null module specification" {
$comparer.GetHashCode($null) | Should -Not -BeNull
}
}
Context "Invalid ModuleSpecification initialization" {
BeforeAll {
$testCases = @(
@{
TestName = "Version+RequiredVersion"
ModuleSpecification = @{ ModuleName = "BadVersionModule"; ModuleVersion = "3.1"; RequiredVersion = "3.1" }
ErrorId = 'ArgumentException'
},
@{
TestName = "NoName"
ModuleSpecification = @{ ModuleVersion = "0.2" }
ErrorId = 'MissingMemberException'
},
@{
TestName = "BadField"
ModuleSpecification = @{ ModuleName = "StrangeFieldModule"; RequiredVersion = "7.4"; Duck = "1.2" }
ErrorId = 'ArgumentException'
},
@{
TestName = "BadType"
ModuleSpecification = @{ ModuleName = "BadTypeModule"; RequiredVersion = "Hello!" }
ErrorId = 'PSInvalidCastException'
}
)
}
It "Cannot create from a null argument" {
{ [ModuleSpecification]::new($null) } | Should -Throw
}
It "Cannot create from invalid module hashtables: <TestName>" -TestCases $testCases {
param([string]$TestName, [hashtable]$ModuleSpecification)
{ [ModuleSpecification]::new($ModuleSpecification) } | Should -Throw -ErrorId $ErrorId
}
}
}