Files
winget-pkgs/Tools/Modules/YamlCreate/YamlCreate.InstallerDetection/YamlCreate.InstallerDetection.Tests.ps1
T

389 lines
15 KiB
PowerShell

BeforeAll {
# Import the module to test
$ModulePath = Split-Path -Parent $PSCommandPath
Import-Module (Join-Path $ModulePath 'YamlCreate.InstallerDetection.psd1') -Force
# Create stub functions for external dependencies that may not be available
# These are typically provided by external modules like MSI or Windows SDK tools
$Script:AddedGetMSITable = $false
if (-not (Get-Command Get-MSITable -ErrorAction SilentlyContinue)) {
function Global:Get-MSITable {
param([string]$Path)
return $null
}
$Script:AddedGetMSITable = $true
}
$Script:AddedGetMSIProperty = $false
if (-not (Get-Command Get-MSIProperty -ErrorAction SilentlyContinue)) {
function Global:Get-MSIProperty {
param([string]$Path, [string]$Property)
return $null
}
$Script:AddedGetMSIProperty = $true
}
$Script:AddedGetWin32ModuleResource = $false
if (-not (Get-Command Get-Win32ModuleResource -ErrorAction SilentlyContinue)) {
function Global:Get-Win32ModuleResource {
param([string]$Path, [switch]$DontLoadResource)
return @()
}
$Script:AddedGetWin32ModuleResource = $true
}
}
AfterAll {
# Clean up stub functions that were created in BeforeAll to prevent them from persisting in the session
if ($Script:AddedGetMSITable) { Remove-Item Function:\Get-MSITable -ErrorAction SilentlyContinue }
if ($Script:AddedGetMSIProperty) { Remove-Item Function:\Get-MSIProperty -ErrorAction SilentlyContinue }
if ($Script:AddedGetWin32ModuleResource) { Remove-Item Function:\Get-Win32ModuleResource -ErrorAction SilentlyContinue }
}
Describe 'YamlCreate.InstallerDetection Module' {
Context 'Module Import' {
It 'Should import the module successfully' {
Get-Module 'YamlCreate.InstallerDetection' | Should -Not -BeNullOrEmpty
}
It 'Should export all expected functions' {
$ExportedFunctions = (Get-Module 'YamlCreate.InstallerDetection').ExportedFunctions.Keys
$ExpectedFunctions = @(
'Get-OffsetBytes'
'Get-PESectionTable'
'Test-IsZip'
'Test-IsMsix'
'Test-IsMsi'
'Test-IsWix'
'Test-IsNullsoft'
'Test-IsInno'
'Test-IsBurn'
'Test-IsFont'
'Resolve-InstallerType'
)
foreach ($Function in $ExpectedFunctions) {
$ExportedFunctions | Should -Contain $Function
}
}
}
}
Describe 'Get-OffsetBytes' {
Context 'Valid input' {
It 'Should extract bytes at the correct offset without little endian' {
$ByteArray = [byte[]](0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08)
$Result = Get-OffsetBytes -ByteArray $ByteArray -Offset 2 -Length 3
$Result | Should -Be @(0x03, 0x04, 0x05)
}
It 'Should extract bytes with little endian ordering' {
$ByteArray = [byte[]](0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08)
$Result = Get-OffsetBytes -ByteArray $ByteArray -Offset 2 -Length 3 -LittleEndian $true
$Result | Should -Be @(0x05, 0x04, 0x03)
}
It 'Should extract a single byte' {
$ByteArray = [byte[]](0x01, 0x02, 0x03, 0x04)
$Result = Get-OffsetBytes -ByteArray $ByteArray -Offset 1 -Length 1
$Result | Should -Be @(0x02)
}
It 'Should extract bytes from the start of array' {
$ByteArray = [byte[]](0x0A, 0x0B, 0x0C, 0x0D)
$Result = Get-OffsetBytes -ByteArray $ByteArray -Offset 0 -Length 2
$Result | Should -Be @(0x0A, 0x0B)
}
It 'Should extract bytes to the end of array' {
$ByteArray = [byte[]](0x01, 0x02, 0x03, 0x04)
$Result = Get-OffsetBytes -ByteArray $ByteArray -Offset 2 -Length 2
$Result | Should -Be @(0x03, 0x04)
}
}
Context 'Edge cases' {
It 'Should return empty array when offset exceeds array length' {
$ByteArray = [byte[]](0x01, 0x02, 0x03, 0x04)
$Result = Get-OffsetBytes -ByteArray $ByteArray -Offset 10 -Length 2
$Result | Should -BeNullOrEmpty
}
}
}
Describe 'Get-PESectionTable' {
Context 'Invalid files' {
It 'Should return null for non-existent file' -Skip {
# Skipping as it attempts to read a non-existent file which causes errors
$Result = Get-PESectionTable -Path 'C:\NonExistent\File.exe'
$Result | Should -BeNullOrEmpty
}
It 'Should return null for a text file' {
$TempFile = New-TemporaryFile
Set-Content -Path $TempFile.FullName -Value 'This is not a PE file'
$Result = Get-PESectionTable -Path $TempFile.FullName
$Result | Should -BeNullOrEmpty
Remove-Item $TempFile.FullName -Force
}
It 'Should return null for file without MZ signature' {
$TempFile = New-TemporaryFile
[byte[]](0x00, 0x00, 0x00, 0x00) * 16 | Set-Content -Path $TempFile.FullName -AsByteStream
$Result = Get-PESectionTable -Path $TempFile.FullName
$Result | Should -BeNullOrEmpty
Remove-Item $TempFile.FullName -Force
}
}
}
Describe 'Test-IsZip' {
Context 'Valid ZIP files' {
It 'Should return true for a valid ZIP file' {
$TempFile = New-TemporaryFile
# ZIP file signature: PK\x03\x04
$ZipHeader = [byte[]](0x50, 0x4B, 0x03, 0x04) + ([byte[]](0x00) * 100)
Set-Content -Path $TempFile.FullName -Value $ZipHeader -AsByteStream
$Result = Test-IsZip -Path $TempFile.FullName
$Result | Should -Be $true
Remove-Item $TempFile.FullName -Force
}
}
Context 'Invalid ZIP files' {
It 'Should return false for a non-ZIP file' {
$TempFile = New-TemporaryFile
Set-Content -Path $TempFile.FullName -Value 'This is not a ZIP file'
$Result = Test-IsZip -Path $TempFile.FullName
$Result | Should -Be $false
Remove-Item $TempFile.FullName -Force
}
It 'Should return false for a file with incorrect header' {
$TempFile = New-TemporaryFile
[byte[]](0x00, 0x01, 0x02, 0x03) | Set-Content -Path $TempFile.FullName -AsByteStream
$Result = Test-IsZip -Path $TempFile.FullName
$Result | Should -Be $false
Remove-Item $TempFile.FullName -Force
}
}
}
Describe 'Test-IsMsix' {
Context 'Non-ZIP files' {
It 'Should return false for a non-ZIP file' {
$TempFile = New-TemporaryFile
Set-Content -Path $TempFile.FullName -Value 'This is not a ZIP file'
$Result = Test-IsMsix -Path $TempFile.FullName
$Result | Should -Be $false
Remove-Item $TempFile.FullName -Force
}
}
Context 'ZIP files without MSIX indicators' {
It 'Should return false for a regular ZIP file without MSIX indicators' -Skip {
# This test requires creating a complete ZIP archive
# Skipped as it requires significant setup
}
}
}
Describe 'Test-IsMsi' {
Context 'Non-MSI files' {
It 'Should return false for a text file' {
$TempFile = New-TemporaryFile
Set-Content -Path $TempFile.FullName -Value 'This is not an MSI file'
$Result = Test-IsMsi -Path $TempFile.FullName
$Result | Should -Be $false
Remove-Item $TempFile.FullName -Force
}
It 'Should return false for a random binary file' {
$TempFile = New-TemporaryFile
[byte[]](0x00, 0x01, 0x02, 0x03) * 25 | Set-Content -Path $TempFile.FullName -AsByteStream
$Result = Test-IsMsi -Path $TempFile.FullName
$Result | Should -Be $false
Remove-Item $TempFile.FullName -Force
}
}
}
Describe 'Test-IsWix' {
Context 'Non-MSI files' {
It 'Should return false for a text file' {
$TempFile = New-TemporaryFile
Set-Content -Path $TempFile.FullName -Value 'This is not a WIX file'
$Result = Test-IsWix -Path $TempFile.FullName
$Result | Should -Be $false
Remove-Item $TempFile.FullName -Force
}
}
}
Describe 'Test-IsNullsoft' {
Context 'Non-PE files' {
It 'Should return false for a text file' {
$TempFile = New-TemporaryFile
Set-Content -Path $TempFile.FullName -Value 'This is not a PE file'
$Result = Test-IsNullsoft -Path $TempFile.FullName
$Result | Should -Be $false
Remove-Item $TempFile.FullName -Force
}
It 'Should return false for a file without PE structure' {
$TempFile = New-TemporaryFile
[byte[]](0x00, 0x01, 0x02, 0x03) * 25 | Set-Content -Path $TempFile.FullName -AsByteStream
$Result = Test-IsNullsoft -Path $TempFile.FullName
$Result | Should -Be $false
Remove-Item $TempFile.FullName -Force
}
}
}
Describe 'Test-IsInno' {
Context 'Non-PE files' {
It 'Should return false for a text file' {
$TempFile = New-TemporaryFile
Set-Content -Path $TempFile.FullName -Value 'This is not a PE file'
$Result = Test-IsInno -Path $TempFile.FullName
$Result | Should -Be $false
Remove-Item $TempFile.FullName -Force
}
}
}
Describe 'Test-IsBurn' {
Context 'Non-PE files' {
It 'Should return false for a text file' {
$TempFile = New-TemporaryFile
Set-Content -Path $TempFile.FullName -Value 'This is not a PE file'
$Result = Test-IsBurn -Path $TempFile.FullName
$Result | Should -Be $false
Remove-Item $TempFile.FullName -Force
}
It 'Should return false for a random binary file' {
$TempFile = New-TemporaryFile
[byte[]](0x00, 0x01, 0x02, 0x03) * 25 | Set-Content -Path $TempFile.FullName -AsByteStream
$Result = Test-IsBurn -Path $TempFile.FullName
$Result | Should -Be $false
Remove-Item $TempFile.FullName -Force
}
}
}
Describe 'Test-IsFont' {
Context 'Valid font files' {
It 'Should return true for a TrueType font (TTF)' {
$TempFile = New-TemporaryFile
# TTF signature: 0x00, 0x01, 0x00, 0x00
$TTFHeader = [byte[]](0x00, 0x01, 0x00, 0x00) + ([byte[]](0x00) * 100)
Set-Content -Path $TempFile.FullName -Value $TTFHeader -AsByteStream
$Result = Test-IsFont -Path $TempFile.FullName
$Result | Should -Be $true
Remove-Item $TempFile.FullName -Force
}
It 'Should return true for an OpenType font (OTF)' {
$TempFile = New-TemporaryFile
# OTF signature: OTTO (0x4F, 0x54, 0x54, 0x4F)
$OTFHeader = [byte[]](0x4F, 0x54, 0x54, 0x4F) + ([byte[]](0x00) * 100)
Set-Content -Path $TempFile.FullName -Value $OTFHeader -AsByteStream
$Result = Test-IsFont -Path $TempFile.FullName
$Result | Should -Be $true
Remove-Item $TempFile.FullName -Force
}
It 'Should return true for a TrueType Collection (TTC)' {
$TempFile = New-TemporaryFile
# TTC signature: ttcf (0x74, 0x74, 0x63, 0x66)
$TTCHeader = [byte[]](0x74, 0x74, 0x63, 0x66) + ([byte[]](0x00) * 100)
Set-Content -Path $TempFile.FullName -Value $TTCHeader -AsByteStream
$Result = Test-IsFont -Path $TempFile.FullName
$Result | Should -Be $true
Remove-Item $TempFile.FullName -Force
}
}
Context 'Non-font files' {
It 'Should return false for a text file' {
$TempFile = New-TemporaryFile
Set-Content -Path $TempFile.FullName -Value 'This is not a font file'
$Result = Test-IsFont -Path $TempFile.FullName
$Result | Should -Be $false
Remove-Item $TempFile.FullName -Force
}
It 'Should return false for a file with incorrect header' {
$TempFile = New-TemporaryFile
[byte[]](0xFF, 0xFF, 0xFF, 0xFF) | Set-Content -Path $TempFile.FullName -AsByteStream
$Result = Test-IsFont -Path $TempFile.FullName
$Result | Should -Be $false
Remove-Item $TempFile.FullName -Force
}
}
}
Describe 'Resolve-InstallerType' {
Context 'Font files' {
It 'Should identify TrueType font files' {
$TempFile = New-TemporaryFile
$TTFHeader = [byte[]](0x00, 0x01, 0x00, 0x00) + ([byte[]](0x00) * 100)
Set-Content -Path $TempFile.FullName -Value $TTFHeader -AsByteStream
$Result = Resolve-InstallerType -Path $TempFile.FullName
$Result | Should -Be 'font'
Remove-Item $TempFile.FullName -Force
}
It 'Should identify OpenType font files' {
$TempFile = New-TemporaryFile
$OTFHeader = [byte[]](0x4F, 0x54, 0x54, 0x4F) + ([byte[]](0x00) * 100)
Set-Content -Path $TempFile.FullName -Value $OTFHeader -AsByteStream
$Result = Resolve-InstallerType -Path $TempFile.FullName
$Result | Should -Be 'font'
Remove-Item $TempFile.FullName -Force
}
It 'Should identify TrueType Collection files' {
$TempFile = New-TemporaryFile
$TTCHeader = [byte[]](0x74, 0x74, 0x63, 0x66) + ([byte[]](0x00) * 100)
Set-Content -Path $TempFile.FullName -Value $TTCHeader -AsByteStream
$Result = Resolve-InstallerType -Path $TempFile.FullName
$Result | Should -Be 'font'
Remove-Item $TempFile.FullName -Force
}
}
Context 'ZIP files' {
It 'Should identify basic ZIP files (or MSIX based on internal structure)' -Skip {
# This test requires a complete valid ZIP structure which Test-IsMsix will try to extract
# Skipping as creating a proper ZIP archive is complex and Test-IsMsix will fail on malformed ZIPs
$TempFile = New-TemporaryFile
$ZipHeader = [byte[]](0x50, 0x4B, 0x03, 0x04) + ([byte[]](0x00) * 100)
Set-Content -Path $TempFile.FullName -Value $ZipHeader -AsByteStream
$Result = Resolve-InstallerType -Path $TempFile.FullName
# Could be 'zip' or 'msix' depending on whether Test-IsMsix can successfully extract and check
$Result | Should -BeIn @('zip', 'msix', $null)
Remove-Item $TempFile.FullName -Force -ErrorAction SilentlyContinue
}
}
Context 'Unknown files' {
It 'Should return null for unknown file types' {
$TempFile = New-TemporaryFile
Set-Content -Path $TempFile.FullName -Value 'This is an unknown file type'
$Result = Resolve-InstallerType -Path $TempFile.FullName
$Result | Should -BeNullOrEmpty
Remove-Item $TempFile.FullName -Force
}
It 'Should return null for a random binary file' {
$TempFile = New-TemporaryFile
[byte[]](0xFF, 0xAA, 0xBB, 0xCC) * 25 | Set-Content -Path $TempFile.FullName -AsByteStream
$Result = Resolve-InstallerType -Path $TempFile.FullName
$Result | Should -BeNullOrEmpty
Remove-Item $TempFile.FullName -Force
}
}
}