#Requires -Version 5.1 [CmdletBinding()] param() Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' $repositoryRoot = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..\..')) $modulePath = Join-Path $repositoryRoot 'scripts\LegacyCutCoverage.psm1' $manifestPath = Join-Path $repositoryRoot 'scripts\LegacyCutRequirements.json' $entryScriptPath = Join-Path $repositoryRoot 'scripts\Test-LegacyCutCoverage.ps1' Import-Module -Name $modulePath -Force $manifest = Get-Content -LiteralPath $manifestPath -Raw -Encoding UTF8 | ConvertFrom-Json $aliases = @($manifest.activeAliases) $assets = @($manifest.assets) $reachableBuilders = [int] $manifest.reachableBuilders $temporaryBase = [IO.Path]::GetFullPath([IO.Path]::GetTempPath()) $fixtureRoot = [IO.Path]::GetFullPath((Join-Path $temporaryBase ("MBN_STOCK_WEBVIEW-cut-fixture-" + [Guid]::NewGuid().ToString('N')))) $externalRoot = [IO.Path]::GetFullPath((Join-Path $temporaryBase ("MBN_STOCK_WEBVIEW-cut-external-" + [Guid]::NewGuid().ToString('N')))) $junctionPath = Join-Path $fixtureRoot 'FixtureJunction' function Assert-Equal { param( [Parameter(Mandatory = $true)] $Expected, [Parameter(Mandatory = $true)] $Actual, [Parameter(Mandatory = $true)] [string] $Message ) if ($Expected -ne $Actual) { throw "$Message Expected=$Expected Actual=$Actual" } } function Assert-True { param( [Parameter(Mandatory = $true)] [bool] $Condition, [Parameter(Mandatory = $true)] [string] $Message ) if (-not $Condition) { throw $Message } } function Write-FixtureFile { param( [Parameter(Mandatory = $true)] [string] $Root, [Parameter(Mandatory = $true)] [string] $RelativePath, [byte[]] $Content = ([byte[]] @(1)) ) $rootPrefix = $Root.TrimEnd('\', '/') + [IO.Path]::DirectorySeparatorChar $path = [IO.Path]::GetFullPath((Join-Path $Root $RelativePath)) if (-not $path.StartsWith($rootPrefix, [StringComparison]::OrdinalIgnoreCase)) { throw 'Fixture path escaped its temporary root.' } $parent = Split-Path -Parent $path if (-not (Test-Path -LiteralPath $parent -PathType Container)) { New-Item -ItemType Directory -Path $parent -Force | Out-Null } [IO.File]::WriteAllBytes($path, $Content) } function Invoke-FixtureCoverage { param( [object[]] $Requirements = $assets ) return Test-LegacyCutCoverageState ` -CutRoot $fixtureRoot ` -Aliases $aliases ` -AssetRequirements $Requirements ` -ReachableBuilders $reachableBuilders } try { New-Item -ItemType Directory -Path $fixtureRoot -Force | Out-Null New-Item -ItemType Directory -Path $externalRoot -Force | Out-Null foreach ($alias in $aliases) { Write-FixtureFile -Root $fixtureRoot -RelativePath ($alias + '.t2s') } foreach ($asset in $assets) { Write-FixtureFile -Root $fixtureRoot -RelativePath ([string] $asset.Path) } $complete = Invoke-FixtureCoverage Assert-Equal 'Passed' $complete.Status 'A complete fixture must pass.' Assert-Equal 0 $complete.Missing 'The legacy alias result regressed.' Assert-Equal 0 $complete.Unsafe 'The legacy alias safety result regressed.' Assert-Equal $assets.Count $complete.RequiredAssets 'The complete manifest was not inspected.' $entryScriptReport = & $entryScriptPath -CutRoot $fixtureRoot Assert-Equal 'Passed' $entryScriptReport.Status 'The public coverage script must pass the complete fixture.' $cubePath = [string] @($assets | Where-Object { $_.Builder -eq 's5006' -and $_.Kind -eq 'Video' })[0].Path $usVideoPath = [string] @($assets | Where-Object { $_.Builder -eq 's6001' -and $_.Kind -eq 'Video' })[0].Path Remove-Item -LiteralPath (Join-Path $fixtureRoot $cubePath) -Force Remove-Item -LiteralPath (Join-Path $fixtureRoot $usVideoPath) -Force $missing = Invoke-FixtureCoverage Assert-Equal 'Failed' $missing.Status 'Missing builder assets must fail.' Assert-Equal 2 $missing.MissingAssets 'Both missing builder assets must be counted.' Assert-Equal 1 @($missing.AssetFindings | Where-Object { $_.Builder -eq 's5006' -and $_.RelativePath -eq $cubePath -and $_.Status -eq 'Missing' }).Count 'The s5006 video must be reported explicitly.' Assert-Equal 1 @($missing.AssetFindings | Where-Object { $_.Builder -eq 's6001' -and $_.RelativePath -eq $usVideoPath -and $_.Status -eq 'Missing' }).Count 'The s6001 video must be reported explicitly.' Write-FixtureFile -Root $fixtureRoot -RelativePath $cubePath Write-FixtureFile -Root $fixtureRoot -RelativePath $usVideoPath [IO.File]::WriteAllBytes((Join-Path $fixtureRoot $usVideoPath), [byte[]] @()) $empty = Invoke-FixtureCoverage Assert-Equal 1 $empty.UnsafeAssets 'An empty builder asset must be unsafe.' Assert-Equal 'Empty' @($empty.AssetFindings | Where-Object { $_.RelativePath -eq $usVideoPath })[0].Status 'The empty asset status must be explicit.' Write-FixtureFile -Root $fixtureRoot -RelativePath $usVideoPath $escape = Invoke-FixtureCoverage -Requirements @( [pscustomobject]@{ Builder = 'fixture-root-escape' Kind = 'Image' Path = '..\outside.png' } ) Assert-Equal 1 $escape.RootEscapes 'A manifest root escape must be rejected.' Assert-Equal 'RootEscape' $escape.AssetFindings[0].Status 'The root escape status must be explicit.' Write-FixtureFile -Root $externalRoot -RelativePath 'linked.vrv' New-Item -ItemType Junction -Path $junctionPath -Target $externalRoot | Out-Null $reparse = Invoke-FixtureCoverage -Requirements @( [pscustomobject]@{ Builder = 'fixture-reparse' Kind = 'Video' Path = 'FixtureJunction\linked.vrv' } ) Assert-Equal 1 $reparse.ReparseAssets 'A reparse ancestor must be rejected.' Assert-Equal 'Reparse' $reparse.AssetFindings[0].Status 'The reparse status must be explicit.' [IO.Directory]::Delete($junctionPath) Remove-Item -LiteralPath (Join-Path $fixtureRoot '5001.t2s') -Force [IO.File]::WriteAllBytes((Join-Path $fixtureRoot '5006.t2s'), [byte[]] @()) $aliasesRegressed = Invoke-FixtureCoverage Assert-Equal 1 $aliasesRegressed.Missing 'A missing alias must retain the legacy result.' Assert-Equal 1 $aliasesRegressed.Unsafe 'An empty alias must retain the legacy result.' $s6001Videos = @($assets | Where-Object { $_.Builder -eq 's6001' -and $_.Kind -eq 'Video' } | Select-Object -ExpandProperty Path -Unique) Assert-Equal 13 $s6001Videos.Count 'The closed manifest must contain 13 distinct s6001 videos.' Assert-True ($assets.Path -contains $cubePath) 'The closed manifest must contain the s5006 cube video.' [pscustomobject][ordered]@{ Status = 'Passed' ActiveAliases = $aliases.Count RequiredAssets = $assets.Count S6001DistinctVideos = $s6001Videos.Count RootEscapeFixture = 'Passed' ReparseFixture = 'Passed' } } finally { if (Test-Path -LiteralPath $junctionPath) { [IO.Directory]::Delete($junctionPath) } $temporaryPrefix = $temporaryBase.TrimEnd('\', '/') + [IO.Path]::DirectorySeparatorChar foreach ($path in @($fixtureRoot, $externalRoot)) { $resolved = [IO.Path]::GetFullPath($path) if (-not $resolved.StartsWith($temporaryPrefix, [StringComparison]::OrdinalIgnoreCase) -or -not ([IO.Path]::GetFileName($resolved)).StartsWith('MBN_STOCK_WEBVIEW-cut-', [StringComparison]::Ordinal)) { throw 'Refusing to remove a fixture directory outside the intended temporary boundary.' } if (Test-Path -LiteralPath $resolved) { Remove-Item -LiteralPath $resolved -Recurse -Force } } }