tests/Backup-Item.Tests.ps1
|
# Unit tests for Private/Backup-Item.ps1. # # Dot-sources the Private helper directly (it's not exported) so we can test # it in isolation without spinning up the full Invoke-BykaDrBackup machinery. BeforeAll { $PrivateDir = Join-Path $PSScriptRoot '..' 'Private' . (Join-Path $PrivateDir 'Backup-Item.ps1') } Describe 'Backup-Item file mode' { BeforeEach { $script:srcDir = Join-Path $TestDrive 'src' $script:backupDir = Join-Path $TestDrive 'backup' New-Item -ItemType Directory -Path $script:srcDir, $script:backupDir -Force | Out-Null } It 'returns OK with byte-count when the source file exists' { $srcFile = Join-Path $script:srcDir 'file.txt' 'hello world' | Out-File -LiteralPath $srcFile -Encoding utf8 -NoNewline $expectedBytes = (Get-Item -LiteralPath $srcFile).Length $result = Backup-Item -Source $srcFile -BackupDir $script:backupDir -DestSubPath 'sub\file.txt' -Label 'test-file' $result.Status | Should -Be 'OK' $result.Item | Should -Be 'test-file' $result.Detail | Should -Be "$expectedBytes bytes" Test-Path (Join-Path $script:backupDir 'sub\file.txt') | Should -BeTrue } It 'returns SKIP when the source file is missing' { $missingFile = Join-Path $script:srcDir 'nope.txt' $result = Backup-Item -Source $missingFile -BackupDir $script:backupDir -DestSubPath 'sub\nope.txt' -Label 'missing-file' $result.Status | Should -Be 'SKIP' $result.Detail | Should -Be 'Not found' } } Describe 'Backup-Item directory mode (-IsDir)' { BeforeEach { $script:srcDir = Join-Path $TestDrive 'src' $script:backupDir = Join-Path $TestDrive 'backup' New-Item -ItemType Directory -Path $script:srcDir, $script:backupDir -Force | Out-Null } It 'returns OK with file-count when the source dir exists with 3 files' { $srcSub = Join-Path $script:srcDir 'mydir' New-Item -ItemType Directory -Path $srcSub -Force | Out-Null 1..3 | ForEach-Object { 'x' | Out-File -LiteralPath (Join-Path $srcSub "f$_.txt") -Encoding utf8 -NoNewline } $result = Backup-Item -Source $srcSub -BackupDir $script:backupDir -DestSubPath 'sub\mydir' -Label 'test-dir' -IsDir $result.Status | Should -Be 'OK' $result.Detail | Should -Be '3 files' Test-Path (Join-Path $script:backupDir 'sub\mydir\f1.txt') | Should -BeTrue } It 'returns SKIP when the source dir is missing (-IsDir)' { $missingDir = Join-Path $script:srcDir 'nope-dir' $result = Backup-Item -Source $missingDir -BackupDir $script:backupDir -DestSubPath 'sub\nope-dir' -Label 'missing-dir' -IsDir $result.Status | Should -Be 'SKIP' $result.Detail | Should -Be 'Not found' } } Describe 'Backup-Item failure path' { It 'returns FAIL when destination subpath cannot be created (file blocking dir)' { # [G4] code-review F7 + qa F3: NUL-byte triggers are PS-version-fragile. # A more stable failure trigger is to place a FILE at the parent dir # path -- New-Item -ItemType Directory will then fail because the path # already exists as a non-directory. The helper's try/catch must # convert this to Status=FAIL, not propagate. $srcDir = Join-Path $TestDrive 'src-fail' $backupDir = Join-Path $TestDrive 'backup-fail' New-Item -ItemType Directory -Path $srcDir, $backupDir -Force | Out-Null $srcFile = Join-Path $srcDir 'file.txt' 'data' | Out-File -LiteralPath $srcFile -Encoding utf8 -NoNewline # Pre-create a FILE where Backup-Item will try to make a directory. $blockingFilePath = Join-Path $backupDir 'sub' 'block' | Out-File -LiteralPath $blockingFilePath -Encoding utf8 -NoNewline $result = Backup-Item -Source $srcFile -BackupDir $backupDir -DestSubPath 'sub\file.txt' -Label 'fail-test' $result.Status | Should -Be 'FAIL' $result.Detail | Should -Not -BeNullOrEmpty } } Describe 'Backup-Item reparse-point handling (-IsDir)' { It 'refuses to follow a top-level junction whose source is a reparse point' { # [G4] sec F3+F10: if -Source itself is a junction, the helper must # SKIP and report the link target, NOT silently follow it. Documents # the current contract (refuse) -- if behavior ever changes to "follow", # this test forces an explicit update. $realDir = Join-Path $TestDrive 'real' $junction = Join-Path $TestDrive 'junc' $backupDir = Join-Path $TestDrive 'backup-junc' New-Item -ItemType Directory -Path $realDir, $backupDir -Force | Out-Null 'a' | Out-File -LiteralPath (Join-Path $realDir 'f.txt') -Encoding utf8 -NoNewline try { New-Item -ItemType Junction -Path $junction -Target $realDir -ErrorAction Stop | Out-Null } catch { Set-ItResult -Skipped -Because "could not create junction: $($_.Exception.Message)" return } try { $result = Backup-Item -Source $junction -BackupDir $backupDir -DestSubPath 'sub\junc' -Label 'junction-src' -IsDir $result.Status | Should -Be 'SKIP' $result.Detail | Should -Match 'Junction|SymbolicLink' } finally { try { [System.IO.Directory]::Delete($junction, $true) } catch {} } } } |