Files
EvoBGP/scripts/tests/collect-backend-baseline.test.ps1
T
DenozordecandCursor f8e0520817 feat(httpapi): harden control plane and speed up prefix refresh
Очередь job получила lease и fencing, телеметрия и прогресс deploy сохраняются, ревизия пишет manifest входов. Обновление префиксов не переписывает неизменённый снимок, большие наборы идут через COPY, а устаревшая ревизия не попадает в deploy. Бандл ноды кэшируется, prune и постановка job больше не держат горячий путь.

Co-authored-by: Cursor <[email protected]>
2026-11-02 17:23:59 +07:00

47 lines
2.9 KiB
PowerShell

# Offline contract test: no Docker daemon or production access needed.
$ErrorActionPreference = 'Stop'
$repoRoot = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent
$output = Join-Path $repoRoot 'artifacts/backend-baseline/offline-test.json'
$mockState = @{ Calls = [Collections.Generic.List[object]]::new(); EmptyStats = $false }
function docker {
param([Parameter(ValueFromRemainingArguments = $true)][string[]]$DockerArgs)
$mockState.Calls.Add($DockerArgs)
$global:LASTEXITCODE = 0
switch ($DockerArgs[0]) {
'compose' {
if ($DockerArgs -contains 'config') {
'{"services":{"api":{"image":"example/api:test","environment":{"PASSWORD":"MUST_NOT_LEAK"},"command":"MUST_NOT_LEAK","deploy":{"resources":{"limits":{"memory":"280M","cpus":"0.85"}}}}}}'
} else { 'aaaaaaaaaaaa'; 'bbbbbbbbbbbb' }
}
'info' { '{"server_version":"test","os_type":"linux","cpus":2,"memory_bytes":1073741824}' }
'inspect' {
'{"id":"' + $DockerArgs[-1] + '","image_id":"sha256:test","running":true,"memory_limit_bytes":293601280,"oom_killed":false,"restart_count":0}'
}
'stats' {
if ($mockState.EmptyStats) { return }
'{"id":"aaaaaaaaaaaa","cpu_percent":"1.0%","memory_usage":"20MiB / 280MiB"}'
'{"id":"bbbbbbbbbbbb","cpu_percent":"2.0%","memory_usage":"30MiB / 280MiB"}'
}
default { throw 'unexpected Docker operation' }
}
}
& (Join-Path $repoRoot 'scripts/collect-backend-baseline.ps1') -OutputPath $output -Samples 1
$raw = Get-Content -LiteralPath $output -Raw
$result = $raw | ConvertFrom-Json
if ($result.status -ne 'collected') { throw 'collector did not succeed' }
if ($result.containers.Count -ne 2 -or $result.samples[0].containers.Count -ne 2) { throw 'NDJSON multi-container stats were lost' }
if ($raw.Contains('MUST_NOT_LEAK') -or $raw.Contains('PASSWORD')) { throw 'raw Compose secrets leaked' }
if ($result.configured_services[0].memory_limit -ne '280M') { throw 'effective resource limit missing' }
if ($mockState.Calls.Count -eq 0) { throw 'Docker mock was not exercised' }
foreach ($call in $mockState.Calls) {
if ($call[0] -notin @('compose', 'info', 'inspect', 'stats')) { throw 'unexpected operation' }
if ($call[0] -eq 'compose' -and -not ($call -contains 'config' -or $call -contains 'ps')) { throw 'mutating Compose operation' }
}
$mockState.EmptyStats = $true
& (Join-Path $repoRoot 'scripts/collect-backend-baseline.ps1') -OutputPath $output -Samples 1
if ($LASTEXITCODE -ne 2) { throw 'missing stats must exit 2' }
$partial = Get-Content -LiteralPath $output -Raw | ConvertFrom-Json
if ($partial.status -ne 'partial' -or $partial.samples[0].complete -ne $false) { throw 'empty stats reported as complete' }
Write-Output 'PASS: multi-container snapshot, resource projection, secret exclusion, read-only operations, incomplete stats detection'
exit 0