$ErrorActionPreference='Stop'
$repo=Split-Path $PSScriptRoot -Parent
Import-Module (Join-Path $repo 'modules/WefSubscriptions.psm1') -Force
. (Join-Path $repo 'scripts/WecRuntime.ps1')
Add-Type -Path (Join-Path $repo 'scripts/WecRuntimeNative.cs')
$script:count=0
function Assert($Value,$Message) {if (-not $Value) {throw $Message};$script:count++}
function Throws($Action,$Pattern) {$message='';try {& $Action | Out-Null} catch {$message=$_.Exception.Message};Assert ($message -match $Pattern) "Expected $Pattern; received $message"}
function NativeValue([uint32]$Type,$Data,[uint32]$Count=0) {[pscustomobject]@{State='Observed';NativeType=$Type;Data=$Data;Count=$Count;ErrorCode=0;Diagnostic=''}}
# Decode synthetic native-memory buffers, not a mock of the ABI decoder.
$buffer=[Runtime.InteropServices.Marshal]::AllocHGlobal(256)
try {
$zero=New-Object byte[] 256;[Runtime.InteropServices.Marshal]::Copy($zero,0,$buffer,256)
[Runtime.InteropServices.Marshal]::WriteInt32($buffer,12,2)
[Runtime.InteropServices.Marshal]::WriteInt32($buffer,0,-1)
$decoded=[Wela.WecRuntime.Native]::Decode($buffer,16,1)
Assert ($decoded.Data -is [uint32] -and $decoded.Data -eq [uint32]::MaxValue) 'UInt32 error codes keep their unsigned width.'
Throws {[Wela.WecRuntime.Native]::Decode($buffer,16,2)} 'Unexpected EC_VARIANT'
Throws {[Wela.WecRuntime.Native]::Decode($buffer,15,1)} 'Invalid runtime buffer'
[Runtime.InteropServices.Marshal]::WriteInt32($buffer,12,3)
[Runtime.InteropServices.Marshal]::WriteInt64($buffer,0,[DateTime]::UtcNow.ToFileTimeUtc())
Assert (([Wela.WecRuntime.Native]::Decode($buffer,16,6)).Data -is [uint64]) 'FILETIME retains unsigned64 representation.'
[Runtime.InteropServices.Marshal]::WriteInt32($buffer,12,4)
$text=[Text.Encoding]::Unicode.GetBytes("日本語 Fehler`0");$textPointer=[IntPtr]::Add($buffer,64)
[Runtime.InteropServices.Marshal]::Copy($text,0,$textPointer,$text.Length)
[Runtime.InteropServices.Marshal]::WriteIntPtr($buffer,0,$textPointer)
Assert (([Wela.WecRuntime.Native]::Decode($buffer,256,2)).Data -ceq '日本語 Fehler') 'Native strings are Unicode without English parsing.'
[Runtime.InteropServices.Marshal]::WriteIntPtr($buffer,0,[IntPtr]::Add($buffer,256))
Throws {[Wela.WecRuntime.Native]::Decode($buffer,256,2)} 'outside'
[Runtime.InteropServices.Marshal]::WriteInt32($buffer,12,132)
[Runtime.InteropServices.Marshal]::WriteInt32($buffer,8,1)
[Runtime.InteropServices.Marshal]::WriteIntPtr($buffer,0,[IntPtr]::Add($buffer,24))
[Runtime.InteropServices.Marshal]::WriteIntPtr($buffer,24,$textPointer)
Assert (([Wela.WecRuntime.Native]::Decode($buffer,256,5)).Data[0] -ceq '日本語 Fehler') 'Source string-array pointer layout is decoded.'
[Runtime.InteropServices.Marshal]::WriteInt32($buffer,8,4097)
Throws {[Wela.WecRuntime.Native]::Decode($buffer,256,5)} '4096'
[Runtime.InteropServices.Marshal]::WriteInt32($buffer,8,0)
[Runtime.InteropServices.Marshal]::WriteInt32($buffer,12,0)
Assert (([Wela.WecRuntime.Native]::Decode($buffer,16,2)).State -eq 'NotAvailable') 'Null is distinct from a successful nonempty property.'
[Runtime.InteropServices.Marshal]::WriteInt32($buffer,8,12345)
$nativeNull=[Wela.WecRuntime.Native]::Decode($buffer,16,4)
Assert ($nativeNull.State -eq 'NotAvailable' -and $nativeNull.Count -eq 0) 'Native null ignores unused count/union storage, which Windows need not initialize.'
} finally {[Runtime.InteropServices.Marshal]::FreeHGlobal($buffer)}
foreach ($property in @(0,1,5)) {
if ($property -in @(0,1)) {Throws {ConvertTo-WelaWecRuntimeField (NativeValue 2 '2') $property} 'UInt32'}
$nullValue=[pscustomobject]@{State='NotAvailable';NativeType=0;ErrorCode=0;Diagnostic=''}
Assert ((ConvertTo-WelaWecRuntimeField $nullValue $property).Status -eq 'Unknown') 'Missing mandatory runtime values cannot make a complete observation.'
}
Assert ((ConvertTo-WelaWecRuntimeField (NativeValue 2 ([uint32]99)) 0).Status -eq 'Unknown') 'Unknown future native enum keeps uncertainty.'
Assert ((ConvertTo-WelaWecRuntimeField (NativeValue 3 ([uint64]0)) 6).Status -eq 'NotAvailable') 'Zero heartbeat is not a1601 observed timestamp.'
Assert ((ConvertTo-WelaWecRuntimeField (NativeValue 3 ([uint64]::MaxValue)) 6).Status -eq 'Unknown') 'Out-of-range FILETIME is not silently rounded.'
$utc=[DateTime]::SpecifyKind([DateTime]'2025-01-02T03:04:05',[DateTimeKind]::Utc)
$time=ConvertTo-WelaWecRuntimeField (NativeValue 3 ([uint64]$utc.ToFileTimeUtc())) 6
Assert ($time.Value -ceq '2025-01-02T03:04:05.0000000Z') 'FILETIME renders UTC without labeling local time Z.'
$script:scenario='';$script:contextReads=0;$script:definitionReads=0;$script:inventoryReads=0;$script:nativeReads=0
$definitionReader=(Get-Command Get-WelaWecRuntimeDefinition).ScriptBlock
function Reset-Fixture {$script:scenario='';$script:contextReads=0;$script:definitionReads=0;$script:inventoryReads=0;$script:nativeReads=0}
function Get-WelaWecRuntimeContext {
$script:contextReads++
if ($script:scenario -eq 'context-denied') {throw 'Reader context unavailable'}
[pscustomobject]@{Computer='FixtureCollector';ReaderSid=$(if ($script:scenario -eq 'context-drift' -and $script:contextReads -gt 1) {'OTHER'} else {'S-1-5-18'});Host=[pscustomobject]@{Build=26100;DomainRole=3}}
}
function Get-WelaWecRuntimeDefinition {
param($Id)
$script:definitionReads++
if ($script:scenario -eq 'definition-denied') {throw 'Definition access denied'}
[pscustomobject]@{Id=$Id;Type='SourceInitiated';Enabled=$false;Key=$(if ($script:scenario -eq 'definition-drift' -and $script:definitionReads -gt 1) {'changed'} else {'same'});RawXml=''}
}
function Read-WelaWecRuntimeValue {
param($Id,$Source,$Property)
$script:nativeReads++
if (($script:scenario -eq 'field-denied' -and $Property -eq 1) -or ($script:scenario -eq 'one-source-denied' -and $Source -eq 'source2' -and $Property -eq 0)) {return [pscustomobject]@{State='Unknown';NativeType=$null;Count=0;ErrorCode=5;Data=$null;Diagnostic='Localized access denied'}}
switch ($Property) {
0 {NativeValue 2 ([uint32]$(if ($script:scenario -eq 'active') {2} elseif ($script:scenario -eq 'trying') {4} else {1}))}
1 {NativeValue 2 ([uint32]$(if ($script:scenario -eq 'trying') {1722} else {0}))}
2 {NativeValue 4 'Lokalisierte Nachricht