$ErrorActionPreference = "Stop" $root = Split-Path $PSScriptRoot -Parent $scriptPath = Join-Path $root "Upgrade-MinerOpsAgentCredential.ps1" . $scriptPath $script:Passed = 0 $script:BootEventRecords = @() $script:ToXmlCalls = 0 function Assert-True { param( [Parameter(Mandatory)][bool]$Condition, [Parameter(Mandatory)][string]$Message ) if (-not $Condition) { throw $Message } } function Assert-Throws { param( [Parameter(Mandatory)][scriptblock]$Action, [string]$Pattern = "" ) try { & $Action | Out-Null } catch { if ($Pattern -and $_.Exception.Message -notmatch $Pattern) { throw "Expected error '$Pattern', got '$($_.Exception.Message)'." } return } throw "Expected action to fail." } function Invoke-ParserTest { param( [Parameter(Mandatory)][string]$Name, [Parameter(Mandatory)][scriptblock]$Action ) & $Action $script:Passed++ Write-Host "PASS: $Name" } function New-TestKernelBootXml { param( [string]$Namespace = "http://schemas.microsoft.com/win/2004/08/events/event", [string]$BootTypeContent = '0', [switch]$OmitSystem, [switch]$OmitEventData, [switch]$DuplicateEventData ) $system = if ($OmitSystem) { "" } else { @" 27 1 4 33 0 42 System "@ } $eventData = if ($OmitEventData) { "" } else { " $BootTypeContent" } if ($DuplicateEventData) { $eventData += "`n $BootTypeContent" } return "`n$system$eventData`n" } function New-TestEventRecord { param( [AllowNull()]$ProviderName = "Microsoft-Windows-Kernel-Boot", [AllowNull()]$Id = [int]27, [AllowNull()]$RecordId = [long]42, [AllowNull()]$Version = [byte]1, [AllowNull()]$Xml = (New-TestKernelBootXml) ) $record = [pscustomobject]@{ ProviderName = $ProviderName Id = $Id RecordId = $RecordId Version = $Version XmlPayload = $Xml } $record | Add-Member -MemberType ScriptMethod -Name ToXml -Value { $script:ToXmlCalls++ return $this.XmlPayload } return $record } function Get-WinEvent { param($FilterHashtable, $ErrorAction) return $script:BootEventRecords } Invoke-ParserTest "conventional namespaced Event XML and typed metadata parse" { $parsed = ConvertFrom-MinerOpsKernelBootEventRecord ` -EventRecord (New-TestEventRecord) Assert-True ($parsed.ProviderName -ceq "Microsoft-Windows-Kernel-Boot") "Typed provider was not retained." Assert-True ($parsed.EventId -is [int] -and $parsed.EventId -eq 27) ` "Typed event ID was not retained." Assert-True ($parsed.RecordId -is [long] -and $parsed.RecordId -eq 42) ` "Typed record ID was not retained." Assert-True ($parsed.Version -is [byte] -and $parsed.Version -eq 1) ` "Typed event version was not retained." Assert-True ($parsed.BootType -is [UInt32] -and $parsed.BootType -eq 0) ` "BootType payload was not parsed." } Invoke-ParserTest "supported event version zero parses" { $parsed = ConvertFrom-MinerOpsKernelBootEventRecord ` -EventRecord (New-TestEventRecord -Version ([byte]0)) Assert-True ($parsed.Version -eq 0) "Version zero was not accepted." } Invoke-ParserTest "production Get-WinEvent path invokes ToXml parser" { $script:ToXmlCalls = 0 $script:BootEventRecords = @( New-TestEventRecord -RecordId ([long]43) ) $identifier = Get-MinerOpsBootIdentifier Assert-True ($identifier -ceq "windows-full-boot-event-v1:000000000000002b") ` "Production event path returned the wrong identifier." Assert-True ($script:ToXmlCalls -eq 1) ` "Production event path did not invoke ToXml exactly once." } Invoke-ParserTest "typed metadata is authoritative over XML scalar metadata" { $xml = (New-TestKernelBootXml).Replace( "27", "999" ).Replace( "42", "999" ) $parsed = ConvertFrom-MinerOpsKernelBootEventRecord ` -EventRecord (New-TestEventRecord -Xml $xml) Assert-True ($parsed.EventId -eq 27 -and $parsed.RecordId -eq 42) ` "XML scalar metadata overrode typed EventRecord properties." } Invoke-ParserTest "null typed RecordId fails closed" { Assert-Throws { ConvertFrom-MinerOpsKernelBootEventRecord ` -EventRecord (New-TestEventRecord -RecordId $null) } "metadata" } Invoke-ParserTest "wrong typed provider fails closed" { Assert-Throws { ConvertFrom-MinerOpsKernelBootEventRecord -EventRecord ` (New-TestEventRecord -ProviderName "Unexpected-Provider") } "metadata" } Invoke-ParserTest "wrong typed event ID fails closed" { Assert-Throws { ConvertFrom-MinerOpsKernelBootEventRecord ` -EventRecord (New-TestEventRecord -Id ([int]28)) } "metadata" } Invoke-ParserTest "wrong RecordId type fails closed" { Assert-Throws { ConvertFrom-MinerOpsKernelBootEventRecord ` -EventRecord (New-TestEventRecord -RecordId ([UInt64]42)) } "metadata" } Invoke-ParserTest "null event version fails closed" { Assert-Throws { ConvertFrom-MinerOpsKernelBootEventRecord ` -EventRecord (New-TestEventRecord -Version $null) } "metadata" } Invoke-ParserTest "unsupported event version fails closed" { Assert-Throws { ConvertFrom-MinerOpsKernelBootEventRecord ` -EventRecord (New-TestEventRecord -Version ([byte]2)) } "unsupported" } Invoke-ParserTest "unexpected Event XML namespace fails closed" { Assert-Throws { ConvertFrom-MinerOpsKernelBootEventRecord -EventRecord ` (New-TestEventRecord -Xml (New-TestKernelBootXml ` -Namespace "urn:unexpected")) } "root" } Invoke-ParserTest "malformed Event XML fails closed" { Assert-Throws { ConvertFrom-MinerOpsKernelBootEventRecord ` -EventRecord (New-TestEventRecord -Xml "") } "malformed" } Invoke-ParserTest "missing System element fails closed" { Assert-Throws { ConvertFrom-MinerOpsKernelBootEventRecord -EventRecord ` (New-TestEventRecord -Xml (New-TestKernelBootXml -OmitSystem)) } "schema" } Invoke-ParserTest "missing EventData fails closed" { Assert-Throws { ConvertFrom-MinerOpsKernelBootEventRecord -EventRecord ` (New-TestEventRecord -Xml (New-TestKernelBootXml -OmitEventData)) } "schema" } Invoke-ParserTest "duplicated EventData fails closed" { Assert-Throws { ConvertFrom-MinerOpsKernelBootEventRecord -EventRecord ` (New-TestEventRecord -Xml ` (New-TestKernelBootXml -DuplicateEventData)) } "schema" } Invoke-ParserTest "missing BootType fails closed" { Assert-Throws { ConvertFrom-MinerOpsKernelBootEventRecord -EventRecord ` (New-TestEventRecord -Xml (New-TestKernelBootXml ` -BootTypeContent '')) } "schema" } Invoke-ParserTest "duplicate BootType fails closed" { $payload = '0' + '0' Assert-Throws { ConvertFrom-MinerOpsKernelBootEventRecord -EventRecord ` (New-TestEventRecord -Xml (New-TestKernelBootXml ` -BootTypeContent $payload)) } "ambiguous" } Invoke-ParserTest "nonnumeric BootType fails closed" { Assert-Throws { ConvertFrom-MinerOpsKernelBootEventRecord -EventRecord ` (New-TestEventRecord -Xml (New-TestKernelBootXml ` -BootTypeContent 'full')) } "canonical" } Invoke-ParserTest "noncanonical BootType fails closed" { Assert-Throws { ConvertFrom-MinerOpsKernelBootEventRecord -EventRecord ` (New-TestEventRecord -Xml (New-TestKernelBootXml ` -BootTypeContent '00')) } "canonical" } Invoke-ParserTest "structured BootType content fails closed" { Assert-Throws { ConvertFrom-MinerOpsKernelBootEventRecord -EventRecord ` (New-TestEventRecord -Xml (New-TestKernelBootXml ` -BootTypeContent ` '0')) } "schema" } Invoke-ParserTest "BootType outside UInt32 fails closed" { Assert-Throws { ConvertFrom-MinerOpsKernelBootEventRecord -EventRecord ` (New-TestEventRecord -Xml (New-TestKernelBootXml ` -BootTypeContent ` '4294967296')) } "invalid" } Invoke-ParserTest "nonzero BootType is not a full-boot anchor" { $script:BootEventRecords = @( New-TestEventRecord -Xml (New-TestKernelBootXml ` -BootTypeContent '1') ) Assert-Throws { Get-MinerOpsBootIdentifier } "could not be verified" } Invoke-ParserTest "empty event query fails closed" { $script:BootEventRecords = @() Assert-Throws { Get-MinerOpsBootIdentifier } "could not be verified" } Invoke-ParserTest "duplicate qualifying record IDs fail closed" { $script:BootEventRecords = @( New-TestEventRecord -RecordId ([long]42) New-TestEventRecord -RecordId ([long]43) New-TestEventRecord -RecordId ([long]42) ) Assert-Throws { Get-MinerOpsBootIdentifier } "could not be verified" } Invoke-ParserTest "equal stored and current anchors deny reset" { Assert-Throws { Assert-MinerOpsBootEpochChanged ` -StoredBootIdentifier "windows-full-boot-event-v1:000000000000002a" ` -CurrentBootIdentifier "windows-full-boot-event-v1:000000000000002a" } "without a verified full Restart" } Invoke-ParserTest "strictly greater current anchor passes ordering" { Assert-MinerOpsBootEpochChanged ` -StoredBootIdentifier "windows-full-boot-event-v1:000000000000002a" ` -CurrentBootIdentifier "windows-full-boot-event-v1:000000000000002b" } Invoke-ParserTest "smaller current anchor fails closed" { Assert-Throws { Assert-MinerOpsBootEpochChanged ` -StoredBootIdentifier "windows-full-boot-event-v1:000000000000002a" ` -CurrentBootIdentifier "windows-full-boot-event-v1:0000000000000029" } "older than the" } Invoke-ParserTest "malformed stored anchor fails closed" { Assert-Throws { Assert-MinerOpsBootEpochChanged ` -StoredBootIdentifier "windows-full-boot-event-v1:not-a-record" ` -CurrentBootIdentifier "windows-full-boot-event-v1:000000000000002b" } "canonical" } Write-Host "$script:Passed boot-event parser tests passed."