Assert-SameFile.ps1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
<#PSScriptInfo
.VERSION 1.0.1 .AUTHOR Roman Kuzmin .COPYRIGHT (c) Roman Kuzmin .TAGS Test .GUID 1707aec3-6f77-41bd-8df4-953c7704f4a6 .LICENSEURI http://www.apache.org/licenses/LICENSE-2.0 .PROJECTURI https://github.com/nightroman/PowerShelf #> <# .Synopsis Compares the sample and result files. .Description This script automates one typical test scenario, it compares the sample and result files and performs copy and view operations if the sample is missing (nor yet created) or the result is different (potentially valid but changed so that the sample may have to be updated after review). If the result is missing then the test fails. If the sample is missing then a warning is written and the sample is created as a copy of the result. The target directory is also created if it does not exist. If files are different then the test either fails or, if View is specified, writes a warning, invokes View, and then prompts to update the sample. File comparison is done via MD5 hashes, it is fast and suitable for large files. But there is a tiny chance that file differences are not detected. .Parameter Sample Specifies the sample file path. If it does not exist then it is created as a copy of the result. .Parameter Result Specifies the result file path. The file must exist. .Parameter View Specifies a command invoked when the files are different. It is an application name or a script block. The arguments are file paths. .Example Assert-SameFile Sample.log Result.log Merge.exe This command compares Sample.log and Result.log at the current location and uses Merge.exe for viewing differences (Merge.exe and file paths are passed in Start-Process). .Example Assert-SameFile Sample.log Result.log {git diff --no-index $args[0] $args[1]} This command uses git in order to view changes. git requires more arguments than Merge.exe above, so that the proper script block is used as a command. .Link https://github.com/nightroman/PowerShelf #> param( [Parameter(Mandatory=1)] [string]$Sample , [Parameter(Mandatory=1)] [string]$Result , $View ) $ErrorActionPreference = 'Stop' # result must exist $fileResult = [System.IO.FileInfo]$PSCmdlet.GetUnresolvedProviderPathFromPSPath($Result) if (!$fileResult.Exists) { Write-Error "Missing result file '$Result'." } # make missing sample $fileSample = [System.IO.FileInfo]$PSCmdlet.GetUnresolvedProviderPathFromPSPath($Sample) if (!$fileSample.Exists) { $null = [System.IO.Directory]::CreateDirectory($fileSample.DirectoryName) Copy-Item -LiteralPath $fileResult.FullName -Destination $fileSample.FullName -Force Write-Warning "Created missing sample file '$Sample'." return } # compare $same = $fileResult.Length -eq $fileSample.Length if ($same) { $md5 = [System.Security.Cryptography.MD5]::Create() $reader = $fileSample.OpenRead() try { $1 = [Guid]$md5.ComputeHash($reader) $reader.Close() $2 = [Guid]$md5.ComputeHash(($reader = $fileResult.OpenRead())) $same = $1 -eq $2 } finally { $reader.Close() } } # pass if ($same) { return } # fail if (!$View) { Write-Error "Different sample '$Sample' and result '$Result'." } Write-Warning "Different sample '$Sample' and result '$Result'." # start view if ($View -is [scriptblock]) { & $View $fileSample.FullName $fileResult.FullName } elseif ($View -is [string]) { Start-Process $View ('"{0}" "{1}"' -f $fileSample.FullName, $fileResult.FullName) } else { Write-Error "Invalid view command: '$View'." } # choice, cast is for v2.0 function Get-Choice($Caption, $Message, $Choices) { $Host.UI.PromptForChoice($Caption, $Message, [System.Management.Automation.Host.ChoiceDescription[]]$Choices, 0) } function New-Choice { New-Object System.Management.Automation.Host.ChoiceDescription $args } # prompt switch(Get-Choice 'Different result' 'How would you like to proceed?' @( New-Choice '&0. Ignore' 'Do nothing.' New-Choice '&1. Update' 'Copy result to sample.' New-Choice '&2. Abort' 'Write terminating error.' )) { 1 { Copy-Item -LiteralPath $fileResult.FullName -Destination $fileSample.FullName -Force } 2 { Write-Error "Different sample '$Sample' and result '$Result'." } } |