MSIX.Tests/MSIX.Trace.Tests.ps1
|
BeforeAll { Import-Module (Resolve-Path (Join-Path $PSScriptRoot '..\MSIX.psd1')) -Force } AfterAll { Remove-Module MSIX -ErrorAction SilentlyContinue } Describe 'Trace Fixup parser' -Tag 'Trace' { Context 'ConvertFrom-MsixTraceLine' { It 'Parses a filesystem failure line' { $line = '[00:00:01.234 8472:A1B] CreateFileW: \\?\C:\Program Files\WindowsApps\app\app.log -> ACCESS_DENIED' $r = ConvertFrom-MsixTraceLine -Line $line $r.Function | Should -Be 'CreateFileW' $r.Result | Should -Be 'ACCESS_DENIED' $r.Path | Should -Match 'app\.log' $r.Category | Should -Be 'filesystem' $r.ProcessId | Should -Be 8472 } It 'Parses a registry SUCCESS line' { $line = '[00:00:02.000 8472:A1B] RegOpenKeyExW: HKLM\SOFTWARE\Vendor -> SUCCESS' $r = ConvertFrom-MsixTraceLine -Line $line $r.Function | Should -Be 'RegOpenKeyExW' $r.Result | Should -Be 'SUCCESS' $r.Category | Should -Be 'registry' } It 'Returns nothing on a non-matching line' { ConvertFrom-MsixTraceLine -Line 'some random debug output' | Should -BeNullOrEmpty } It 'Returns nothing on an empty line' { ConvertFrom-MsixTraceLine -Line '' | Should -BeNullOrEmpty } } Context 'Get-MsixTraceFailure' { BeforeAll { $script:LogPath = Join-Path $env:TEMP "trace-$([guid]::NewGuid().ToString('N').Substring(0,8)).log" @( '[00:00:01.001 1234:A1] CreateFileW: C:\Windows\SysWOW64\settings.cfg -> NAME_NOT_FOUND' '[00:00:01.002 1234:A1] CreateFileW: C:\Program Files\WindowsApps\app\out.log -> ACCESS_DENIED' '[00:00:01.003 1234:A1] RegOpenKeyExW: HKLM\SOFTWARE\Foo -> SUCCESS' '[00:00:01.004 1234:A1] RegSetValueExW: HKLM\SOFTWARE\Foo\Bar -> ACCESS_DENIED' 'random unrelated debug output' ) | Set-Content $script:LogPath } AfterAll { Remove-Item $script:LogPath -Force -ErrorAction SilentlyContinue } It 'Returns only failing rows' { $f = Get-MsixTraceFailure -Path $script:LogPath $f.Count | Should -Be 3 $f.Result | Should -Not -Contain 'SUCCESS' } It 'Drops unparseable lines' { $r = Get-MsixTraceOutput -Path $script:LogPath $r.Function | Should -Not -Contain $null } } Context 'ConvertFrom-MsixTraceToFinding' { It 'Maps WindowsApps writes to FileRedirectionFixup' { $f = [pscustomobject]@{ Function = 'CreateFileW' Path = 'C:\Program Files\WindowsApps\app\out.log' Result = 'ACCESS_DENIED' Category = 'filesystem' ProcessId= 1; ThreadId='A' } $finding = ConvertFrom-MsixTraceToFinding -Failures @($f) $finding.Category | Should -Be 'FileRedirectionFixup' $finding.Severity | Should -Be 'Error' } It 'Maps SysWOW64 reads to WorkingDirectory' { $f = [pscustomobject]@{ Function = 'CreateFileW' Path = 'C:\Windows\SysWOW64\settings.cfg' Result = 'NAME_NOT_FOUND' Category = 'filesystem' ProcessId= 1; ThreadId='A' } $finding = ConvertFrom-MsixTraceToFinding -Failures @($f) $finding.Category | Should -Be 'WorkingDirectory' } It 'Maps HKLM access denied to RegLegacyFixups' { $f = [pscustomobject]@{ Function = 'RegSetValueExW' Path = 'HKLM\SOFTWARE\Foo' Result = 'ACCESS_DENIED' Category = 'registry' ProcessId= 1; ThreadId='A' } $finding = ConvertFrom-MsixTraceToFinding -Failures @($f) $finding.Category | Should -Be 'RegLegacyFixups' } It 'Deduplicates by category + leaf' { $f1 = [pscustomobject]@{ Function='CreateFileW'; Path='C:\Program Files\WindowsApps\a.log'; Result='ACCESS_DENIED'; ProcessId=1; ThreadId='A' } $f2 = [pscustomobject]@{ Function='CreateFileW'; Path='C:\Program Files\WindowsApps\a.log'; Result='ACCESS_DENIED'; ProcessId=2; ThreadId='B' } (ConvertFrom-MsixTraceToFinding -Failures @($f1, $f2)).Count | Should -Be 1 } } } |