param([string]$BuildFolder = 'Release') $ErrorActionPreference = 'Stop' Add-Type -AssemblyName PresentationFramework [void][Reflection.Assembly]::LoadFrom((Join-Path $PSScriptRoot "DCT_test/bin/$BuildFolder/DCT_test.exe")) function Assert-True($value, $message) { if (!$value) { throw $message } } $packet = [DCT_test.DctPacket]::Create(0xA3, [byte[]](1, 161, 0x12, 0x34), 0) $bytes = $packet.Encode() $buffer = New-Object 'System.Collections.Generic.List[byte]' $buffer.AddRange([byte[]]$bytes[0..3]) Assert-True (([DCT_test.DctPacket]::ParseStream($buffer)).Count -eq 0) 'Partial frame accepted' $buffer.AddRange([byte[]]$bytes[4..($bytes.Length-1)]) $parsed = [DCT_test.DctPacket]::ParseStream($buffer) Assert-True ($parsed.Count -eq 1 -and $buffer.Count -eq 0) 'Split frame failed' Assert-True (($parsed[0].Encode() -join ',') -eq ($bytes -join ',')) 'Roundtrip changed bytes' $bad = [byte[]]$bytes.Clone() $bad[$bad.Length-2] = $bad[$bad.Length-2] -bxor 1 $buffer.AddRange($bad) $buffer.AddRange($bytes) Assert-True (([DCT_test.DctPacket]::ParseStream($buffer)).Count -eq 1) 'Corrupt frame recovery failed' $reader = New-Object DCT_test.LogFileReader $logDirectory = Join-Path $PSScriptRoot '../refer/mdb_dbc_log' Get-ChildItem $logDirectory -Filter '*log.txt' | ForEach-Object { $result = $reader.Load($_.FullName) Assert-True $result.Success ($_.Name + ': ' + $result.ErrorMessage) Write-Output ($_.Name + ': ' + $result.TotalRecords + ' packets OK') } Write-Output 'PASS: split frames, checksum recovery, byte roundtrip, real log loading' # Exercise the actual WPF START handler without opening a window or a server. # An empty source must stay stopped and must not generate substitute telemetry. $previousContext = [Threading.SynchronizationContext]::Current [Threading.SynchronizationContext]::SetSynchronizationContext( (New-Object Windows.Threading.DispatcherSynchronizationContext)) $window = $null try { $window = New-Object DCT_test.MainWindow $flags = [Reflection.BindingFlags]'Instance,NonPublic' $windowType = $window.GetType() Assert-True ($window.FindName('ComboNetworkMode').SelectedIndex -eq 1) 'Current app AP/LAN default missing' Assert-True ($window.FindName('TextDropTitle').Text.Contains('(.txt)')) 'Drop guide must match supported TXT log input' [void]$windowType.GetMethod('BtnClearFile_Click', $flags).Invoke($window, [object[]]@($null, $null)) [void]$windowType.GetMethod('StartTelemetryStreaming', $flags).Invoke($window, $null) Assert-True (-not $windowType.GetField('_isPlaying', $flags).GetValue($window)) 'Empty source started playback' Assert-True ($windowType.GetField('_loadedLogRecords', $flags).GetValue($window).Count -eq 0) 'Empty source generated packets' foreach ($removedName in @('RadioModeSim', 'RadioModeFile', 'ComboProfile', 'ComboRate', 'GridTxSignals', 'BtnPlay', 'BtnPause', 'BtnStop')) { Assert-True ($null -eq $window.FindName($removedName)) ('Removed control still present: ' + $removedName) } foreach ($retainedName in @('ComboSpeed', 'CheckLoop', 'GridClients', 'TextLogConsole')) { Assert-True ($null -ne $window.FindName($retainedName)) ('Missing playback control: ' + $retainedName) } $console = $window.FindName('TextLogConsole') $expander = $window.FindName('PacketLogExpander') Assert-True ($null -ne $expander -and -not $expander.IsExpanded) 'Packet log must start collapsed' $append = $windowType.GetMethod('AppendLog', $flags) [void]$append.Invoke($window, [object[]]@('collapsed-log-marker')) Assert-True ($console.Text.Contains('collapsed-log-marker')) 'Collapsing must not stop log collection' for ($i = 0; $i -lt 3; $i++) { $expander.IsExpanded = $true $window.Dispatcher.Invoke([Action]{}, [Windows.Threading.DispatcherPriority]::ContextIdle) # A hidden Window does not arrange its content; measure the root directly. $window.Content.Measure([Windows.Size]::new(1120,820)) $window.Content.Arrange([Windows.Rect]::new(0,0,1120,820)) $window.Content.UpdateLayout() Assert-True ($expander.Parent.RowDefinitions[1].Height.IsStar -and $console.ActualHeight -gt 100) 'Expanded log must use available height' Assert-True ($console.Text.Contains('collapsed-log-marker')) 'Expanding must retain collected logs' $expander.IsExpanded = $false $window.Dispatcher.Invoke([Action]{}, [Windows.Threading.DispatcherPriority]::ContextIdle) $window.Content.UpdateLayout() Assert-True ($expander.Parent.RowDefinitions[1].Height.IsAuto -and $expander.ActualHeight -lt 80) 'Collapsed log must show only its header' } [void]$windowType.GetMethod('BtnClearLog_Click', $flags).Invoke($window, [object[]]@($null, $null)) Assert-True ($console.Text.Length -eq 0) 'Clear log must remain usable' Write-Output 'PASS: packet log default collapsed, retained collection, expanded/collapsed layout (3 rounds), clear log' Write-Output 'PASS: log-only WPF controls, empty-source START stays stopped, client list and packet console retained' } finally { if ($null -ne $window) { $window.Close() } [Threading.SynchronizationContext]::SetSynchronizationContext($previousContext) }