187 lines
7.7 KiB
PowerShell
187 lines
7.7 KiB
PowerShell
#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
|
|
}
|
|
}
|
|
}
|