scripts/test-install-cli.ps1
Rama main · réplica de lectura del repositorio original.
$ErrorActionPreference = "Stop"
$root = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)
$installer = Join-Path $root "install-cli.ps1"
function Restore-ProcessEnvironment {
param([string]$Name, [AllowNull()][string]$Value)
if ($null -eq $Value) {
Remove-Item -LiteralPath "Env:$Name" -ErrorAction SilentlyContinue
} else {
Set-Item -LiteralPath "Env:$Name" -Value $Value
}
}
$oldArch = $env:FIRECRAB_CLI_ARCH
$oldReleaseBase = $env:FIRECRAB_RELEASE_BASE
$oldAllowFileUrl = $env:FIRECRAB_TEST_ALLOW_FILE_URL
$oldProcessPath = $env:Path
$oldUserPath = [Environment]::GetEnvironmentVariable("Path", "User")
$scratch = Join-Path ([System.IO.Path]::GetTempPath()) ("firecrab-cli-test-" + [guid]::NewGuid())
try {
$env:FIRECRAB_CLI_ARCH = "x86_64"
$asset = & $installer -PrintAsset
if ($asset -ne "firecrab-cli-x86_64-windows.zip") {
throw "unexpected Windows asset: $asset"
}
$env:FIRECRAB_CLI_ARCH = "ARM64"
$armAsset = & $installer -PrintAsset
if ($armAsset -ne "firecrab-cli-aarch64-windows.zip") {
throw "unexpected Windows ARM64 asset: $armAsset"
}
$env:FIRECRAB_CLI_ARCH = "x86_64"
$url = & $installer -Version "1.2.3" -PrintUrl
$expected = "https://github.com/SteelCrab/firecrab/releases/download/v1.2.3/firecrab-cli-x86_64-windows.zip"
if ($url -ne $expected) {
throw "unexpected Windows URL: $url"
}
$check = & $installer -Check -InstallDir (Join-Path $scratch "bin")
if ($check -notmatch "would install") {
throw "check mode did not describe the install"
}
$release = Join-Path $scratch "releases\latest\download"
$payload = Join-Path $scratch "payload"
$installDir = Join-Path $scratch "bin"
New-Item -ItemType Directory -Force -Path $release, $payload | Out-Null
$fixtureBinary = Join-Path $payload "firecrab.exe"
[System.IO.File]::WriteAllText($fixtureBinary, "firecrab fixture")
$archive = Join-Path $release $asset
Compress-Archive -Path $fixtureBinary -DestinationPath $archive -Force
$sums = Join-Path $release "SHA256SUMS"
$hash = (Get-FileHash -Algorithm SHA256 $archive).Hash.ToLowerInvariant()
[System.IO.File]::WriteAllText($sums, "$hash $asset`n")
$env:FIRECRAB_RELEASE_BASE = ([System.Uri](Join-Path $scratch "releases")).AbsoluteUri.TrimEnd("/")
$env:FIRECRAB_TEST_ALLOW_FILE_URL = "1"
& $installer -InstallDir $installDir
$installed = Join-Path $installDir "firecrab.exe"
if (-not (Test-Path -LiteralPath $installed -PathType Leaf)) {
throw "installer did not create firecrab.exe"
}
if ([System.IO.File]::ReadAllText($installed) -ne "firecrab fixture") {
throw "installer changed the fixture binary"
}
[System.IO.File]::WriteAllText($fixtureBinary, "firecrab replacement")
Compress-Archive -Path $fixtureBinary -DestinationPath $archive -Force
$hash = (Get-FileHash -Algorithm SHA256 $archive).Hash.ToLowerInvariant()
[System.IO.File]::WriteAllText($sums, "$hash $asset`n")
& $installer -InstallDir $installDir
if ([System.IO.File]::ReadAllText($installed) -ne "firecrab replacement") {
throw "installer did not atomically replace an existing binary"
}
$victim = Join-Path $scratch "victim.txt"
[System.IO.File]::WriteAllText($victim, "keep victim")
Remove-Item -LiteralPath $installed -Force
New-Item -ItemType SymbolicLink -Path $installed -Target $victim | Out-Null
& $installer -InstallDir $installDir
if ([System.IO.File]::ReadAllText($victim) -ne "keep victim" -or
((Get-Item -LiteralPath $installed).Attributes -band [System.IO.FileAttributes]::ReparsePoint) -ne 0) {
throw "installer followed the destination symlink"
}
Push-Location $scratch
try {
& $installer -InstallDir "relative-bin"
} finally {
Pop-Location
}
$relativeBin = Join-Path $scratch "relative-bin"
if (-not (Test-Path -LiteralPath (Join-Path $relativeBin "firecrab.exe"))) {
throw "relative installation did not resolve against the PowerShell location"
}
# Linux PowerShell cannot persist the Windows user PATH registry value.
# Keep that assertion on Windows; Docker checks the process value instead.
$pathScope = if ($IsWindows) { "User" } else { "Process" }
$userPathEntries = @([Environment]::GetEnvironmentVariable("Path", $pathScope) -split ";" | Where-Object { $_ })
if ($userPathEntries -notcontains $relativeBin) {
throw "relative installation did not persist an absolute PATH"
}
if ($userPathEntries -notcontains $installDir) {
throw "installer did not add its directory to the user PATH"
}
[System.IO.File]::AppendAllText($archive, "tampered")
$rejected = $false
try {
& $installer -InstallDir $installDir
} catch {
if ($_.Exception.Message -notmatch "checksum mismatch") { throw }
$rejected = $true
}
if (-not $rejected -or [System.IO.File]::ReadAllText($installed) -ne "firecrab replacement") {
throw "tampered release was not rejected with the installed binary preserved"
}
foreach ($unsafeBase in @("http://example.test/releases", "ftp://example.test/releases")) {
$env:FIRECRAB_RELEASE_BASE = $unsafeBase
try {
& $installer -PrintUrl
throw "unsafe release URL was accepted: $unsafeBase"
} catch {
if ($_.Exception.Message -match "unsafe release URL was accepted") { throw }
}
}
$env:FIRECRAB_RELEASE_BASE = ([System.Uri](Join-Path $scratch "releases")).AbsoluteUri.TrimEnd("/")
Remove-Item -LiteralPath Env:FIRECRAB_TEST_ALLOW_FILE_URL
try {
& $installer -PrintUrl
throw "file release URL was accepted without explicit test opt-in"
} catch {
if ($_.Exception.Message -match "was accepted without") { throw }
}
} finally {
[Environment]::SetEnvironmentVariable("Path", $oldUserPath, "User")
$env:Path = $oldProcessPath
Restore-ProcessEnvironment -Name "FIRECRAB_CLI_ARCH" -Value $oldArch
Restore-ProcessEnvironment -Name "FIRECRAB_RELEASE_BASE" -Value $oldReleaseBase
Restore-ProcessEnvironment -Name "FIRECRAB_TEST_ALLOW_FILE_URL" -Value $oldAllowFileUrl
Remove-Item -LiteralPath $scratch -Recurse -Force -ErrorAction SilentlyContinue
}
Write-Output "all tests passed"