Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions Tools/windows/Tests/ValidationRunner.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,87 @@ function Test-MultiProjectProtocolContracts([string] $stubSource, [string] $gate
}
throw "RED: multi-project expected actual $prefix rejection"
}
$selectionAst = [Management.Automation.Language.Parser]::ParseInput($gateSource, [ref]$null, [ref]$null)
$observer = $selectionAst.Find({
param($node)
$node -is [Management.Automation.Language.FunctionDefinitionAst] -and $node.Name -ceq "Get-MultiProjectObservation"
}, $true)
$selectionCheck = @($observer.FindAll({
param($node)
$node -is [Management.Automation.Language.AssignmentStatementAst] -and
$node.Extent.Text.Contains('$projectSelected -eq') -and $node.Extent.Text.Contains('$loopSelected -eq')
}, $true))
Assert-MultiCase ($selectionCheck.Count -eq 1) "owner selection predicate is not uniquely source-derived"
$ownerSelectionPredicate = [scriptblock]::Create($selectionCheck[0].Extent.Text)
foreach ($case in @(
@{ surface = "project"; selected = $true; project = $true; loop = $false; accepted = $true },
@{ surface = "workspace"; selected = $true; project = $false; loop = $true; accepted = $true },
@{ surface = "project"; selected = $true; project = $true; loop = $true; accepted = $false },
@{ surface = "workspace"; selected = $true; project = $true; loop = $true; accepted = $false },
@{ surface = "project"; selected = $true; project = $false; loop = $true; accepted = $false },
@{ surface = "workspace"; selected = $true; project = $true; loop = $false; accepted = $false },
@{ surface = "project"; selected = $false; project = $true; loop = $false; accepted = $false },
@{ surface = "workspace"; selected = $false; project = $false; loop = $true; accepted = $false },
@{ surface = "project"; selected = $false; project = $false; loop = $false; accepted = $true }
)) {
Invoke-MultiCase ("destination-scoped sidebar owner " + ($case | ConvertTo-Json -Compress)) -Negative:(-not $case.accepted) {
$surface = $case.surface; $selected = $case.selected
$projectSelected = $case.project; $loopSelected = $case.loop; $matches = $true
. $ownerSelectionPredicate
Assert-MultiCase ($matches -eq $case.accepted) "sidebar owner selection contradicts its destination"
return "Source-derived owner predicate only; exactly-one roster and native UIA remain runtime evidence."
}
}
$selectionCountCheck = @($observer.FindAll({
param($node)
$node -is [Management.Automation.Language.AssignmentStatementAst] -and
$node.Extent.Text.Contains('$selectedSidebarIds.Count -eq 1')
}, $true))
Assert-MultiCase ($selectionCountCheck.Count -eq 1) "sidebar cardinality predicate is not uniquely source-derived"
$sidebarSelectionPredicate = [scriptblock]::Create($selectionCountCheck[0].Extent.Text)
foreach ($case in @(
@{ ids = @("expected"); accepted = $true },
@{ ids = @(); accepted = $false },
@{ ids = @("wrong"); accepted = $false },
@{ ids = @("expected", "wrong"); accepted = $false },
@{ ids = @("expected", "expected"); accepted = $false }
)) {
Invoke-MultiCase ("exact sidebar selection " + ($case | ConvertTo-Json -Compress)) -Negative:(-not $case.accepted) {
$selectedSidebarIds = $case.ids; $expectedSidebarId = "expected"; $matches = $true
. $sidebarSelectionPredicate
Assert-MultiCase ($matches -eq $case.accepted) "sidebar accepts an absent, wrong or duplicate selection"
return "Source-derived count/identity predicate; no live UIA claim."
}
}
$projectSelection = [ordered]@{ automationId = "open-project-1"; name = "Selected project" }
$loopSelection = [ordered]@{ automationId = "loop-row-2"; name = "Wrong loop" }
$attentionSelection = [ordered]@{ automationId = "needs-you-row-3"; name = "Selected attention alias" }
foreach ($case in @(
@{ rows = @($projectSelection); accepted = $true; extras = 0 },
@{ rows = @($projectSelection, $attentionSelection); accepted = $true; extras = 1 },
@{ rows = @(); accepted = $false; extras = 0 },
@{ rows = @($loopSelection); accepted = $false; extras = 0 },
@{ rows = @($projectSelection, $loopSelection); accepted = $false; extras = 0 },
@{ rows = @($attentionSelection); accepted = $false; extras = 1 }
)) {
Invoke-MultiCase ("navigation selection excludes logged extras " + ($case | ConvertTo-Json -Compress)) -Negative:(-not $case.accepted) {
$output = @(Get-MultiProjectSidebarSelection $case.rows 6>&1)
$selection = @($output | Where-Object { $_ -is [Collections.IDictionary] })
$logs = @($output | Where-Object { $_ -is [Management.Automation.InformationRecord] })
Assert-MultiCase ($selection.Count -eq 1) "navigation classification omitted its result"
$selectedSidebarIds = @($selection[0].navigation | ForEach-Object { $_.automationId })
$expectedSidebarId = $projectSelection.automationId; $matches = $true
. $sidebarSelectionPredicate
Assert-MultiCase ($matches -eq $case.accepted -and $selection[0].extras.Count -eq $case.extras) `
"navigation cardinality counted a retained alias or accepted wrong/missing navigation"
Assert-MultiCase ($logs.Count -eq $case.extras) "retained alias was not logged exactly once"
if ($case.extras -gt 0) {
Assert-MultiCase ($logs[0].ToString().Contains($attentionSelection.automationId) -and
$logs[0].ToString().Contains($attentionSelection.name)) "alias log omitted exact ID or name"
}
return "Source-derived navigation predicate; retained extras logged, native static selection deferred to #801."
}
}
$eventStart = [DateTime]::Parse("2026-10-01T18:29:43.1462496Z").ToUniversalTime()
$eventEnd = $eventStart.AddSeconds(1)
$eventProcess = [pscustomobject]@{ Id = 5832; StartTime = $eventStart }
Expand Down Expand Up @@ -1170,6 +1251,42 @@ function Test-MultiProjectProtocolContracts([string] $stubSource, [string] $gate
$captureReader = { param($element, [bool] $includeContent) $element.Capture($includeContent) }
$capturePrior = @{ ownership = "owned"; finalPID = @{ value = 4242 }
automationID = @{ value = "canvas-card-1983941480823304696" } }
foreach ($clipped in @("empty", "zero")) {
Invoke-MultiCase ("selected alias name tolerates " + $clipped + " bounds") {
$states = @((New-MultiCaptureState),(New-MultiCaptureState),(New-MultiCaptureState))
$states[1].rect = if ($clipped -ceq "empty") { [System.Windows.Rect]::Empty } else { [System.Windows.Rect]::new(0,0,0,0) }
$mock = New-MultiCaptureMock $states
$before = Read-MultiProjectOwnershipSnapshot $mock $captureReader
$name = Read-MultiProjectSelectedName $mock $before 4242 $captureReader
Assert-MultiCase ($name -ceq "Alpha loop" -and $mock.calls -eq 3 -and
-not ($mock.order -contains "BOUNDS")) "clipped alias rejected or bounds read for name-only logging"
return "Owned cached ID/runtime verified before name and after; no geometry or live UIA claim."
}
}
foreach ($mutation in @("foreign", "zero", "identity", "runtime", "name-type", "name-unsupported", "after-foreign", "after-runtime")) {
Invoke-MultiCase ("selected alias name rejects " + $mutation) -Negative {
$states = @((New-MultiCaptureState),(New-MultiCaptureState),(New-MultiCaptureState))
switch ($mutation) {
"foreign" { $states[1].pid = 7777 }
"zero" { $states[1].pid = 0 }
"identity" { $states[1].id = "different-row" }
"runtime" { $states[1].runtime = @(3,42,99) }
"name-type" { $states[1].name = 7 }
"name-unsupported" { $states[1].name = [System.Windows.Automation.AutomationElement]::NotSupported }
"after-foreign" { $states[2].pid = 7777 }
"after-runtime" { $states[2].runtime = @(3,42,99) }
}
$mock = New-MultiCaptureMock $states
$before = Read-MultiProjectOwnershipSnapshot $mock $captureReader
$prefix = if ($mutation -cin @("foreign", "after-foreign")) { "MULTIPROJECT_PRIVACY:" } else { "MULTIPROJECT_METADATA:" }
$rejection = Reject-MultiCase { Read-MultiProjectSelectedName $mock $before 4242 $captureReader } $prefix
Assert-MultiCase (-not ($mock.order -contains "BOUNDS")) "name-only logging read bounds"
if ($mutation -cin @("foreign", "zero", "identity", "runtime")) {
Assert-MultiCase (-not ($mock.order -contains "NAME")) "selected alias name read before cached ownership guard"
}
return $rejection
}
}
Invoke-MultiCase "fresh cached capture verifies owned metadata before and after content" {
$mock = New-MultiCaptureMock @((New-MultiCaptureState),(New-MultiCaptureState),(New-MultiCaptureState))
$evidence = Get-MultiProjectElementEvidence $mock 4242 $capturePrior "functional/owned" $captureReader
Expand Down
Loading
Loading