Exercises Sync-ManagedDestination directly against a throwaway source/destination pair: idempotent second install (no writes, no backups), removal of a stale-and-untouched file, protection of a stale-but-locally-modified file (backed up, left in place, warned), a foreign file that was never installed staying untouched, and a dry run that reports the planned removal without any side effects. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
51 lines
3.6 KiB
PowerShell
51 lines
3.6 KiB
PowerShell
[CmdletBinding()]
|
|
param()
|
|
$ErrorActionPreference = 'Stop'
|
|
$root = Split-Path $PSScriptRoot -Parent
|
|
. (Join-Path $PSScriptRoot 'lib/manifest.ps1')
|
|
|
|
$work = Join-Path ([System.IO.Path]::GetTempPath()) ("ai-config-manifest-test-" + [Guid]::NewGuid())
|
|
New-Item $work -ItemType Directory -Force | Out-Null
|
|
try {
|
|
$source = Join-Path $work 'source'
|
|
$destination = Join-Path $work 'destination'
|
|
New-Item $source -ItemType Directory -Force | Out-Null
|
|
Set-Content (Join-Path $source 'a.md') 'A' -Encoding UTF8 -NoNewline
|
|
Set-Content (Join-Path $source 'b.md') 'B' -Encoding UTF8 -NoNewline
|
|
Set-Content (Join-Path $source 'c.md') 'C' -Encoding UTF8 -NoNewline
|
|
|
|
$out1 = @(Sync-ManagedDestination -Source $source -Destination $destination -Stamp 'run1')
|
|
if (@($out1 | Where-Object { $_ -like 'CREATE*' }).Count -ne 3) { throw "Expected three CREATE lines on first install: $($out1 -join '; ')" }
|
|
|
|
$out2 = @(Sync-ManagedDestination -Source $source -Destination $destination -Stamp 'run2')
|
|
if (@($out2 | Where-Object { $_ -notlike 'UNCHANGED*' -and $_ -notlike 'SOURCE *' }).Count -ne 0) { throw "Second identical install was not a no-op: $($out2 -join '; ')" }
|
|
if (Test-Path (Join-Path $destination 'backups/run2')) { throw 'Idempotent install must not create a backup.' }
|
|
|
|
Set-Content (Join-Path $destination 'foreign.md') 'mine' -Encoding UTF8 -NoNewline
|
|
|
|
Remove-Item (Join-Path $source 'b.md') -Force
|
|
Remove-Item (Join-Path $source 'c.md') -Force
|
|
Set-Content (Join-Path $destination 'c.md') 'locally changed' -Encoding UTF8 -NoNewline
|
|
|
|
$out3 = @(Sync-ManagedDestination -Source $source -Destination $destination -Stamp 'run3')
|
|
if (@($out3 | Where-Object { $_ -match 'REMOVE.*b\.md' }).Count -ne 1) { throw "Expected b.md to be removed: $($out3 -join '; ')" }
|
|
if (Test-Path (Join-Path $destination 'b.md')) { throw 'b.md should have been removed: it was untouched by the user and dropped from source.' }
|
|
if (@($out3 | Where-Object { $_ -match 'WARN.*c\.md.*changed locally' }).Count -ne 1) { throw "Expected c.md to be flagged as locally modified: $($out3 -join '; ')" }
|
|
if (-not (Test-Path (Join-Path $destination 'c.md'))) { throw 'A locally modified stale file must not be removed.' }
|
|
if ((Get-Content (Join-Path $destination 'c.md') -Raw) -ne 'locally changed') { throw 'c.md content must be preserved exactly.' }
|
|
if ((Get-Content (Join-Path $destination 'foreign.md') -Raw) -ne 'mine') { throw 'A file this setup never installed must never be touched.' }
|
|
if (-not (Test-Path (Join-Path $destination 'backups/run3/b.md'))) { throw 'b.md should have been backed up before removal.' }
|
|
if (-not (Test-Path (Join-Path $destination 'backups/run3/c.md'))) { throw 'c.md should have been backed up even though it was left in place.' }
|
|
|
|
Remove-Item (Join-Path $source 'a.md') -Force
|
|
$beforeDry = @(Get-ChildItem $destination -Recurse -File | Sort-Object FullName | ForEach-Object FullName)
|
|
$outDry = @(Sync-ManagedDestination -Source $source -Destination $destination -Stamp 'dry' -DryRun)
|
|
$afterDry = @(Get-ChildItem $destination -Recurse -File | Sort-Object FullName | ForEach-Object FullName)
|
|
if (Compare-Object $beforeDry $afterDry) { throw 'A dry run must not change the destination at all.' }
|
|
if (@($outDry | Where-Object { $_ -match 'DRYRUN REMOVE.*a\.md' }).Count -ne 1) { throw "Dry run should report the planned removal without performing it: $($outDry -join '; ')" }
|
|
|
|
Write-Output 'PASS managed manifest: idempotent, stale removal, modified-file protection, foreign files preserved, dry run side-effect free'
|
|
} finally {
|
|
Remove-Item $work -Recurse -Force -ErrorAction SilentlyContinue
|
|
}
|