Tests/Private/Test-FileByteIntegrity.Tests.ps1
|
BeforeAll { . "$PSScriptRoot/../../Private/Test-FileByteIntegrity.ps1" } Describe 'Test-FileByteIntegrity' { BeforeAll { $testDir = Join-Path ([System.IO.Path]::GetTempPath()) "FileByteIntegrityTests_$([guid]::NewGuid().ToString('N'))" New-Item -ItemType Directory -Path $testDir -Force | Out-Null } AfterAll { Remove-Item -Path $testDir -Recurse -Force -ErrorAction SilentlyContinue } Context 'When source file does not exist' { It 'Returns MissingOnSource' { $src = Join-Path $testDir 'nonexistent_src.txt' $dst = Join-Path $testDir 'existing_dst.txt' Set-Content -Path $dst -Value 'hello' $result = Test-FileByteIntegrity -SourcePath $src -DestinationPath $dst $result | Should -Be 'MissingOnSource' } } Context 'When destination file does not exist' { It 'Returns MissingOnDestination' { $src = Join-Path $testDir 'existing_src.txt' $dst = Join-Path $testDir 'nonexistent_dst.txt' Set-Content -Path $src -Value 'hello' $result = Test-FileByteIntegrity -SourcePath $src -DestinationPath $dst $result | Should -Be 'MissingOnDestination' } } Context 'When files differ in size' { It 'Returns SizeMismatch' { $src = Join-Path $testDir 'size_src.txt' $dst = Join-Path $testDir 'size_dst.txt' [System.IO.File]::WriteAllBytes($src, [byte[]](1..100)) [System.IO.File]::WriteAllBytes($dst, [byte[]](1..50)) $result = Test-FileByteIntegrity -SourcePath $src -DestinationPath $dst $result | Should -Be 'SizeMismatch' } } Context 'When both files are empty' { It 'Returns Match' { $src = Join-Path $testDir 'empty_src.txt' $dst = Join-Path $testDir 'empty_dst.txt' [System.IO.File]::WriteAllBytes($src, [byte[]]@()) [System.IO.File]::WriteAllBytes($dst, [byte[]]@()) $result = Test-FileByteIntegrity -SourcePath $src -DestinationPath $dst $result | Should -Be 'Match' } } Context 'When files are identical and small (< 8KB)' { It 'Returns Match' { $src = Join-Path $testDir 'small_match_src.bin' $dst = Join-Path $testDir 'small_match_dst.bin' $data = [byte[]](1..100) [System.IO.File]::WriteAllBytes($src, $data) [System.IO.File]::WriteAllBytes($dst, $data) $result = Test-FileByteIntegrity -SourcePath $src -DestinationPath $dst $result | Should -Be 'Match' } } Context 'When small files differ in content' { It 'Returns ByteMismatch' { $src = Join-Path $testDir 'small_diff_src.bin' $dst = Join-Path $testDir 'small_diff_dst.bin' $srcData = [byte[]](1..100) $dstData = [byte[]](1..100) $dstData[50] = 255 # flip one byte [System.IO.File]::WriteAllBytes($src, $srcData) [System.IO.File]::WriteAllBytes($dst, $dstData) $result = Test-FileByteIntegrity -SourcePath $src -DestinationPath $dst $result | Should -Be 'ByteMismatch' } } Context 'When files are identical and large (> 8KB)' { It 'Returns Match' { $src = Join-Path $testDir 'large_match_src.bin' $dst = Join-Path $testDir 'large_match_dst.bin' # 20KB of data $data = [byte[]]::new(20480) [System.Random]::new(42).NextBytes($data) [System.IO.File]::WriteAllBytes($src, $data) [System.IO.File]::WriteAllBytes($dst, $data) $result = Test-FileByteIntegrity -SourcePath $src -DestinationPath $dst $result | Should -Be 'Match' } } Context 'When large files differ in the first chunk' { It 'Returns ByteMismatch' { $src = Join-Path $testDir 'large_head_diff_src.bin' $dst = Join-Path $testDir 'large_head_diff_dst.bin' $data = [byte[]]::new(20480) [System.Random]::new(42).NextBytes($data) [System.IO.File]::WriteAllBytes($src, $data) $dataCopy = [byte[]]::new($data.Length) [System.Array]::Copy($data, $dataCopy, $data.Length) $dataCopy[10] = [byte](($dataCopy[10] + 1) % 256) [System.IO.File]::WriteAllBytes($dst, $dataCopy) $result = Test-FileByteIntegrity -SourcePath $src -DestinationPath $dst $result | Should -Be 'ByteMismatch' } } Context 'When large files differ in the last chunk' { It 'Returns ByteMismatch' { $src = Join-Path $testDir 'large_tail_diff_src.bin' $dst = Join-Path $testDir 'large_tail_diff_dst.bin' $data = [byte[]]::new(20480) [System.Random]::new(42).NextBytes($data) [System.IO.File]::WriteAllBytes($src, $data) $dataCopy = [byte[]]::new($data.Length) [System.Array]::Copy($data, $dataCopy, $data.Length) $dataCopy[$dataCopy.Length - 5] = [byte](($dataCopy[$dataCopy.Length - 5] + 1) % 256) [System.IO.File]::WriteAllBytes($dst, $dataCopy) $result = Test-FileByteIntegrity -SourcePath $src -DestinationPath $dst $result | Should -Be 'ByteMismatch' } } Context 'When large files differ only in the middle (blind spot)' { It 'Returns Match (known limitation — partial check only reads head + tail)' { $src = Join-Path $testDir 'large_mid_diff_src.bin' $dst = Join-Path $testDir 'large_mid_diff_dst.bin' $data = [byte[]]::new(20480) [System.Random]::new(42).NextBytes($data) [System.IO.File]::WriteAllBytes($src, $data) $dataCopy = [byte[]]::new($data.Length) [System.Array]::Copy($data, $dataCopy, $data.Length) # Flip a byte in the middle (between first 8KB and last 8KB) $dataCopy[10000] = [byte](($dataCopy[10000] + 1) % 256) [System.IO.File]::WriteAllBytes($dst, $dataCopy) $result = Test-FileByteIntegrity -SourcePath $src -DestinationPath $dst $result | Should -Be 'Match' } } Context 'When file is exactly 8KB (one chunk boundary)' { It 'Returns Match for identical files' { $src = Join-Path $testDir 'boundary_match_src.bin' $dst = Join-Path $testDir 'boundary_match_dst.bin' $data = [byte[]]::new(8192) [System.Random]::new(42).NextBytes($data) [System.IO.File]::WriteAllBytes($src, $data) [System.IO.File]::WriteAllBytes($dst, $data) $result = Test-FileByteIntegrity -SourcePath $src -DestinationPath $dst $result | Should -Be 'Match' } } } |