Files
ParkingRobot/.task8-sweep/tests/verify_coarse_path_ui.ps1
T

123 lines
7.2 KiB
PowerShell

$ErrorActionPreference = 'Stop'
function Assert-True([bool]$condition, [string]$message) {
if (-not $condition) { throw $message }
}
function Assert-Match([string]$content, [string]$pattern, [string]$message) {
Assert-True ($content -match $pattern) $message
}
function Assert-NotMatch([string]$content, [string]$pattern, [string]$message) {
Assert-True ($content -notmatch $pattern) $message
}
$sourcePath = Join-Path $PSScriptRoot '..\ParkrobTrajplanner\CoarsePath\Test\MovementTest.CoarsePathTest.cs'
Assert-True (Test-Path -LiteralPath $sourcePath) 'P1 coarse-path UI movement-test source must exist.'
$source = Get-Content -Raw -Encoding UTF8 $sourcePath
Assert-Match $source 'class\s+CoarsePathPlanningTest\s*:\s*MovementTest' 'The UI entry must inherit MovementTest.'
Assert-Match $source 'namespace\s+MultiWheelC\s*;' 'MovementTest entries must use the project discovery namespace.'
Assert-Match $source 'CoarsePathPlanningService' 'The UI must keep one shared planning service for map-cache reuse.'
Assert-Match $source 'Task\.Run\s*\(' 'Planning must run in a background Task.'
Assert-Match $source 'CancellationTokenSource' 'The UI must retain a cancellation source for its active task.'
Assert-Match $source 'override\s+void\s+TestStop\s*\(' 'The UI must implement TestStop cancellation.'
Assert-Match $source 'CoarsePathScenarioFactory\.Create\s*\(' 'The UI must expose fixed scenario entries through the factory.'
Assert-Match $source 'ManualCoarsePathObstacle' 'The manual UI must construct typed manual obstacles.'
Assert-Match $source 'CreateManualObstacleDemo\s*\(' 'The manual UI must submit obstacles through the factory.'
Assert-Match $source 'MaximumManualObstacleCount\s*=\s*20' 'The manual UI must bound obstacle input to 20.'
Assert-Match $source 'ReadManualObstacles\s*\(' 'The manual UI must read the requested obstacle sequence.'
Assert-Match $source 'Interlocked\.Increment\s*\(' 'The manual UI must issue a fresh obstacle snapshot version.'
Assert-Match $source 'Circle\s*\(' 'The manual UI must support circle input.'
Assert-Match $source 'AxisAlignedRectangle\s*\(' 'The manual UI must support axis-aligned rectangle input.'
Assert-Match $source 'UI\.GetInput\s*\(' 'The manual demo must accept user input.'
Assert-Match $source 'ReadPositiveTimeoutInput\s*\(' 'The manual UI must read a finite positive timeout.'
Assert-Match $source 'Configuration\.SearchTimeout\s*=\s*searchTimeout' 'The manual UI must apply the timeout to the current job.'
Assert-Match $source 'TimeSpan\.FromSeconds\s*\(' 'The manual timeout must convert seconds to TimeSpan.'
Assert-Match $source 'timeoutSeconds\s*<=\s*0' 'The manual timeout must reject zero and negative values.'
Assert-Match $source 'getCartLocation\s*\(' 'The manual demo must read the AMR body-center pose.'
Assert-Match $source 'DrawLegend\s*\(' 'The painter output must include a visual legend.'
Assert-Match $source 'PlanningGridMap' 'The painter output must consume the planning grid result.'
Assert-Match $source '\.IsOccupied\s*\(' 'The painter output must draw occupied grid cells.'
Assert-Match $source 'ResolutionMm' 'The painter output must draw the grid at its true resolution.'
Assert-Match $source 'SnapshotId' 'The painter output must show the map snapshot identity.'
Assert-Match $source 'IsGearSwitchPoint' 'The painter output must highlight gear-switch points.'
Assert-Match $source 'GoalPositionToleranceMeters' 'The painter output must draw goal tolerance.'
Assert-True (([regex]::Matches($source, 'PathSearchElapsed')).Count -ge 2) 'The status layer and Toast must both show path-search elapsed time.'
Assert-Match $source 'BuildToastMessage[\s\S]*TerminationReason' 'The failure Toast must include the termination reason.'
Assert-Match $source 'ExpandedNodeCount' 'The status layer must show expanded-node statistics.'
Assert-Match $source 'VehicleKinematics\.TryGetMaximumCurvaturePerMeter' 'The status layer must show the effective turning radius.'
Assert-NotMatch $source 'PlanningMapFactory' 'Movement tests must not build maps directly; use CoarsePathPlanningService.'
Assert-NotMatch $source '\.Result\b' 'The UI must not block on Task.Result.'
Assert-NotMatch $source '\.Wait\s*\(' 'The UI must not block the movement-test thread.'
$runnerStart = $source.IndexOf('internal static class CoarsePathPlanningTestRunner')
Assert-True ($runnerStart -ge 0) 'Shared runner source must exist.'
$runnerSource = $source.Substring($runnerStart)
Assert-Match $runnerSource 'RunScenario[\s\S]*getCartLocation\s*\(' 'Fixed scenarios must read the current AMR pose.'
Assert-Match $runnerSource 'CoarsePathScenarioFactory\.Create\s*\(\s*scenario\s*,' 'Fixed scenarios must use the AMR-aware factory overload.'
Assert-Match $runnerSource 'AMR' 'The runner must expose AMR pose diagnostics.'
Assert-Match $runnerSource 'ArgumentException\("AMR' 'Invalid AMR input must be reported without starting planning.'
Assert-Match $runnerSource 'double\.IsNaN|double\.IsInfinity' 'The runner must reject non-finite AMR coordinates.'
Assert-Match $runnerSource 'DrawStatus\s*\([\s\S]*AmrPoseSnapshot' 'Result status must receive the frozen AMR snapshot.'
$inputFailureStart = $runnerSource.IndexOf('internal static void ShowInputFailure')
$inputFailureEnd = $runnerSource.IndexOf('private static void Finish', $inputFailureStart)
Assert-True ($inputFailureStart -ge 0 -and $inputFailureEnd -gt $inputFailureStart) 'Input failure renderer must be isolated before completion handling.'
$inputFailureSource = $runnerSource.Substring($inputFailureStart, $inputFailureEnd - $inputFailureStart)
Assert-Match $inputFailureSource 'Painter\.DrawText\s*\(' 'Invalid AMR input must be shown on the Painter status layer.'
$readmePath = Join-Path $PSScriptRoot '..\ParkrobTrajplanner\CoarsePath\README.md'
Assert-True (Test-Path -LiteralPath $readmePath) 'CoarsePath README must exist beside its module.'
$readme = Get-Content -Raw -Encoding UTF8 $readmePath
foreach ($requiredText in @(
'CoarsePathPlanningV1',
'CoarsePathPlanningTest',
'CreateManualGoalDemo',
'getCartLocation',
'mm',
'deg',
'rad',
'CancellationTokenSource',
'TestStop',
'NoFeasiblePath',
'IsGearSwitchPoint')) {
Assert-True ($readme.Contains($requiredText)) "P1 README must document $requiredText."
}
$readmeStructure = @(
'File Structure',
'Planning Data Flow',
'Build Status and Stop',
'Coordinates and Units',
'Minimal Call Example',
'Cache and SourceVersion',
'Detailed Usage Guide',
'P1 Manual Tests and Visualization',
'Common Errors',
'First-Version Limits',
'CoarsePathPlanningService.Plan(job, cancellationToken)',
'CoarsePathPlanningJob',
'PlanningGridMap',
'SourceVersion',
'CoarsePathPlanningV1',
'CancellationTokenSource',
'NoFeasiblePath',
'IsGearSwitchPoint',
'CreateManualObstacleDemo',
'ManualCoarsePathObstacle',
'manual-user-input',
'0-20',
'PathSearchElapsed',
'1.20 m',
'Reeds-Shepp',
'AxisAlignedRectangle',
'Create(CoarsePathTestScenario scenario, double amrXMillimeters',
'DetectionHeadingRadians',
'../Map/README.md'
)
foreach ($requiredText in $readmeStructure) {
Assert-True ($readme.Contains($requiredText)) "Restructured CoarsePath README must document $requiredText."
}
Write-Output 'Coarse path P1 UI source checks passed.'