ticketmaster/poshspec

[Bug] Package function returns more than one package causing test to fail

megamorf opened this issue · 4 comments

Hey guys,

I'd like to report an issue I ran into when using the package function. Here's my test:

Describe 'Common packages & frameworks' {
    Context 'Visual C++ Runtimes' {
        Package 'Microsoft Visual C++ 2005 Redistributable' Version { Should Be '8.0.61001' }
        Package 'Microsoft Visual C++ 2005 Redistributable (x64)' Version { Should Be '8.0.61000' }
    }
}

When we look at the packages it should be fine:

PS C:\> Get-Package | where name -like "*C++ 2005*" | select name, version

Name                                            Version  
----                                            -------  
Microsoft Visual C++ 2005 Redistributable (x64) 8.0.61000
Microsoft Visual C++ 2005 Redistributable       8.0.61001

But here's the thing - it fails with the following error:

Describing Common packages & frameworks
   Context Visual C++ Runtimes
    [-] Package property 'Version' for 'Microsoft Visual C++ 2005 Redistributable' Should Be '8.0.61001' 361ms
      String lengths are both 9. Strings differ at index 8.
      Expected: {8.0.61001}
      But was:  {8.0.61000}
      -------------------^
      1: Get-Package -Name 'Microsoft Visual C++ 2005 Redistributable' -ErrorAction SilentlyContinue | Select-Object -ExpandProperty 'Version' | Should Be '8.0.61001'
      at Should<End>, C:\Program Files\WindowsPowerShell\Modules\pester\3.4.1\Functions\Assertions\Should.ps1: Zeile 92
      at <ScriptBlock>, <no file>: Zeile 1
      at <ScriptBlock>, C:\Program Files\WindowsPowerShell\Modules\poshspec\2.1.12\Private\Invoke-PoshspecExpression.ps1: Zeile 12
      at Invoke-Test, C:\Program Files\WindowsPowerShell\Modules\pester\3.4.1\Functions\It.ps1: Zeile 253
      at ItImpl, C:\Program Files\WindowsPowerShell\Modules\pester\3.4.1\Functions\It.ps1: Zeile 203
      at It, C:\Program Files\WindowsPowerShell\Modules\pester\3.4.1\Functions\It.ps1: Zeile 117
      at Invoke-PoshspecExpression, C:\Program Files\WindowsPowerShell\Modules\poshspec\2.1.12\Private\Invoke-PoshspecExpression.ps1: Zeile 11
      at Package, C:\Program Files\WindowsPowerShell\Modules\poshspec\2.1.12\Public\Package.ps1: Zeile 42
      at <ScriptBlock>, <no file>: Zeile 3
      at Context, C:\Program Files\WindowsPowerShell\Modules\pester\3.4.1\Functions\Context.ps1: Zeile 66
      at <ScriptBlock>, <no file>: Zeile 2
      at Describe, C:\Program Files\WindowsPowerShell\Modules\pester\3.4.1\Functions\Describe.ps1: Zeile 103
      at <ScriptBlock>, <no file>: Zeile 1
    [+] Package property 'Version' for 'Microsoft Visual C++ 2005 Redistributable (x64)' Should Be '8.0.61000' 359ms

The first package test fails because the Get-Package call in the package function actually returns two results and then expands it into an array and compares the first element of the array against the expected value:

PS C:\> Get-Package -Name 'Microsoft Visual C++ 2005 Redistributable' | select name,version

Name                                            Version
----                                            -------
Microsoft Visual C++ 2005 Redistributable (x64) 8.0.61000
Microsoft Visual C++ 2005 Redistributable       8.0.61001

PS C:\> Get-Package -Name 'Microsoft Visual C++ 2005 Redistributable' -ErrorAction SilentlyContinue | Select-Object -ExpandProperty 'Version'
8.0.61000
8.0.61001

Should this issue have been closed by #26? It seems so.

I'll check this later today and close the issue if it's fixed.

Unfortunately this isn't fixed. I think it'd make sense to change the package selection approach:

So instead of this:

Get-Package -Name "$Target" -ErrorAction SilentlyContinue | Select-Object -First 1

do this:

# Requires PSv4 (http://www.powershellmagazine.com/2014/10/22/foreach-and-where-magic-methods/)
(Get-Package -Name "$Target" -ErrorAction SilentlyContinue).Where({$_.Name -eq "$Target"},'First')

IMO Get-Package is to blame since they use an implicit wildcard for the Name attribute:

PS C:\> Get-Package -Name 'Microsoft Visual C++' | Select Name,Version

Name                                                                                               Version
----                                                                                               -------
Microsoft Visual C++ 2008 Redistributable - x64 9.0.30729.4148                                     9.0.30729.4148
Microsoft Visual C++ 2010  x64 Redistributable - 10.0.40219                                        10.0.40219
Microsoft Visual C++ 2005 Redistributable (x64)                                                    8.0.61000
Microsoft Visual C++ 2010  x86 Redistributable - 10.0.40219                                        10.0.40219
Microsoft Visual C++ 2013 x86 Minimum Runtime - 12.0.21005                                         12.0.21005
Microsoft Visual C++ 2013 x86 Additional Runtime - 12.0.21005                                      12.0.21005
Microsoft Visual C++ 2013 x64 Additional Runtime - 12.0.21005                                      12.0.21005
Microsoft Visual C++ 2008 Redistributable - x64 9.0.30729.6161                                     9.0.30729.6161
Microsoft Visual C++ 2008 Redistributable - x86 9.0.30729.6161                                     9.0.30729.6161
Microsoft Visual C++ 2013 x64 Minimum Runtime - 12.0.21005                                         12.0.21005
Microsoft Visual C++ 2005 Redistributable                                                          8.0.61001
[output omitted]

Looking back at my original example where I tell Get-Package to get me a package with the name of Microsoft Visual C++ 2005 Redistributable it does the following which is always going to fail the current workaround with Select-Object -First 1

PS C:\> Get-Package -Name 'Microsoft Visual C++ 2005 Redistributable' | Select Name,Version

Name                                            Version
----                                            -------
Microsoft Visual C++ 2005 Redistributable (x64) 8.0.61000
Microsoft Visual C++ 2005 Redistributable       8.0.61001

Looks like this was fixed either by an updated PackageManagement Module or Powershell version as I don't see this issue on Window 10.

In any case it seems like simply sorting by name may fix your example.

PS C:\> Get-Package | where name -like "*C++ 2005*" | select name, version

Name                                            Version
----                                            -------
Microsoft Visual C++ 2005 Redistributable (x64) 8.0.61000
Microsoft Visual C++ 2005 Redistributable       8.0.50727.42
PS C:\> Get-Package | where name -like "*C++ 2005*" | select name, version | sort name

Name                                            Version
----                                            -------
Microsoft Visual C++ 2005 Redistributable       8.0.50727.42
Microsoft Visual C++ 2005 Redistributable (x64) 8.0.61000