94 lines
6.3 KiB
PowerShell
94 lines
6.3 KiB
PowerShell
#Requires -Version 5.1
|
|
# Standalone preflight contract checks; synthetic metadata, no Cargo/build/UI.
|
|
$ErrorActionPreference = 'Stop'
|
|
Set-StrictMode -Version Latest
|
|
. (Join-Path $PSScriptRoot 'windows-notices.ps1')
|
|
$fixture = Join-Path ([IO.Path]::GetTempPath()) ('arcadia-notices-' + [guid]::NewGuid().ToString('N'))
|
|
[void][IO.Directory]::CreateDirectory($fixture)
|
|
$utf8 = New-Object Text.UTF8Encoding($false)
|
|
function Write-Fixture([string]$Relative, [string]$Text) {
|
|
$path = Join-Path $fixture $Relative
|
|
[void][IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($path))
|
|
[IO.File]::WriteAllText($path, $Text, $utf8)
|
|
return $path
|
|
}
|
|
$null = Write-Fixture 'LICENSE' 'Synthetic workspace license for tests only'
|
|
$null = Write-Fixture 'Cargo.toml' '[workspace]'
|
|
$null = Write-Fixture 'rust/share/doc/rust/COPYRIGHT.html' 'Synthetic Rust distribution notice'
|
|
$null = Write-Fixture 'rust/share/doc/rust/COPYRIGHT-library.html' 'Synthetic Rust library notice'
|
|
$null = Write-Fixture 'rust/lib/fake.rlib' 'Synthetic target library'
|
|
$packages = @(); $nodes = @(); $lock = @()
|
|
foreach ($name in @('oa-desktop', 'oa-server', 'normal', 'build', 'dev-only', 'unreachable')) {
|
|
$external = $name -notlike 'oa-*'
|
|
$root = if ($external) { "registry/src/test/$name-1.0.0" } else { "workspace/$name" }
|
|
$manifest = Write-Fixture "$root/Cargo.toml" "[package]`nname = `"$name`"`nversion = `"1.0.0`""
|
|
$null = Write-Fixture "$root/src/lib.rs" '// synthetic source'
|
|
$null = Write-Fixture "$root/LICENSE" "Synthetic notice for $name"
|
|
$source = if ($external) { 'registry+https://github.com/rust-lang/crates.io-index' } else { $null }
|
|
$id = $name
|
|
if ($external) {
|
|
$archive = Write-Fixture "registry/cache/test/$name-1.0.0.crate" "Synthetic cached archive $name"
|
|
$sha = (Get-FileHash -LiteralPath $archive -Algorithm SHA256).Hash.ToLowerInvariant()
|
|
$lock += "[[package]]`nname = `"$name`"`nversion = `"1.0.0`"`nsource = `"$source`"`nchecksum = `"$sha`"`n"
|
|
}
|
|
$packages += [pscustomobject]@{ id = $id; name = $name; version = '1.0.0'; source = $source; license = 'MIT'; license_file = $null; manifest_path = $manifest; repository = 'https://example.invalid/test' }
|
|
$deps = @()
|
|
if ($name -eq 'oa-desktop') {
|
|
foreach ($pair in @(@('normal', $null), @('build', 'build'), @('dev-only', 'dev'))) {
|
|
$deps += [pscustomobject]@{ pkg = $pair[0]; dep_kinds = @([pscustomobject]@{ kind = $pair[1] }) }
|
|
}
|
|
}
|
|
$nodes += [pscustomobject]@{ id = $id; deps = $deps; features = @() }
|
|
}
|
|
$null = Write-Fixture 'Cargo.lock' ($lock -join "`n")
|
|
$script:FixtureMetadata = [pscustomobject]@{ packages = $packages; workspace_members = @('oa-desktop', 'oa-server'); resolve = [pscustomobject]@{ nodes = $nodes } }
|
|
function cargo {
|
|
if (($args -join ' ') -notmatch '--locked --offline' -or ($args -join ' ') -notmatch '--filter-platform x86_64-pc-windows-msvc') { throw 'Unexpected Cargo command' }
|
|
$global:LASTEXITCODE = 0
|
|
$script:FixtureMetadata | ConvertTo-Json -Depth 12
|
|
}
|
|
function rustc {
|
|
$global:LASTEXITCODE = 0
|
|
if ($args[0] -eq '-Vv') { return 'rustc synthetic-test' }
|
|
if ($args[1] -eq 'sysroot') { return (Join-Path $fixture 'rust') }
|
|
if ($args[1] -eq 'target-libdir') { return (Join-Path $fixture 'rust/lib') }
|
|
throw 'Unexpected Rust command'
|
|
}
|
|
$manifestPath = Write-Fixture 'supplements/manifest.json' '{"packages":[],"assets":[],"runtimes":[]}'
|
|
function Collect { Get-WindowsNotices $fixture x86_64-pc-windows-msvc $manifestPath '' }
|
|
function Assert([bool]$Condition, [string]$Message) { if (-not $Condition) { throw $Message } }
|
|
function Refuses([string]$Pattern) {
|
|
try { $null = Collect; throw 'Expected preflight refusal' } catch {
|
|
if ($_.Exception.Message -notmatch $Pattern) { throw }
|
|
}
|
|
}
|
|
$result = Collect
|
|
$names = @($result.Inventory.packages | ForEach-Object { $_.name })
|
|
Assert ($names.Count -eq 4 -and $names -contains 'normal' -and $names -contains 'build' -and $names -notcontains 'dev-only' -and $names -notcontains 'unreachable') 'Normal/build graph selection failed'
|
|
Assert ($result.Inventory.rust.notices.Count -eq 2) 'Rust reports missing'
|
|
$before = ($result.Inventory.packages | Where-Object name -eq normal).local_source_sha256['src/lib.rs']
|
|
$null = Write-Fixture 'registry/src/test/normal-1.0.0/src/lib.rs' '// locally changed source'
|
|
$after = ((Collect).Inventory.packages | Where-Object name -eq normal).local_source_sha256['src/lib.rs']
|
|
Assert ($before -ne $after) 'Local source hash was replaced by a cached checksum'
|
|
$null = Write-Fixture 'registry/cache/test/normal-1.0.0.crate' 'Tampered archive'
|
|
Refuses 'Cached crate archive differs'
|
|
$null = Write-Fixture 'registry/cache/test/normal-1.0.0.crate' 'Synthetic cached archive normal'
|
|
$null = Write-Fixture 'registry/src/test/normal-1.0.0/src/lib.rs' 'static FONT: &[u8] = include_bytes!("../font.ttf");'
|
|
$null = Write-Fixture 'registry/src/test/normal-1.0.0/font.ttf' 'Synthetic font bytes'
|
|
Refuses 'Embedded font requires exact notice mapping'
|
|
$null = Write-Fixture 'registry/src/test/normal-1.0.0/src/lib.rs' '// no font'
|
|
$pkg = $script:FixtureMetadata.packages | Where-Object name -eq normal
|
|
$pkg.source = 'git+https://example.invalid/test#123'
|
|
Refuses 'Unsupported source requiring deliberate review'
|
|
$pkg.source = 'registry+https://github.com/rust-lang/crates.io-index'
|
|
$normalHash = (Get-FileHash -LiteralPath (Join-Path $fixture 'registry/cache/test/normal-1.0.0.crate') -Algorithm SHA256).Hash.ToLowerInvariant()
|
|
$bad = [ordered]@{ packages = @([ordered]@{ name = 'normal'; version = '1.0.0'; checksum = $normalHash; notices = @([ordered]@{ file = '../LICENSE'; sha256 = ('0' * 64); url = 'https://example.invalid/test' }) }); assets = @(); runtimes = @() }
|
|
$null = Write-Fixture 'supplements/manifest.json' ($bad | ConvertTo-Json -Depth 8)
|
|
Refuses 'Notice path escapes source root'
|
|
$bad.packages[0].notices[0].file = 'NOTICE.txt'
|
|
$null = Write-Fixture 'supplements/NOTICE.txt' 'Synthetic supplemental notice'
|
|
$null = Write-Fixture 'supplements/manifest.json' ($bad | ConvertTo-Json -Depth 8)
|
|
Refuses 'Supplement changed'
|
|
Write-Output 'PASS: normal/build selection, Rust reports, actual local source hashes, stale archive refusal, unmapped font refusal, unsupported source refusal, traversal refusal, altered supplement refusal.'
|
|
Write-Output "Synthetic fixture retained for inspection: $fixture"
|